blob: 7238c02624043621de5e7b2bf8a074a75408c329 [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>
Rashmica Gupta52328cb2023-02-15 10:38:16 +11009#include <libpldm/transport.h>
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -050010#include <libpldm/transport/af-mctp.h>
Rashmica Gupta52328cb2023-02-15 10:38:16 +110011#include <libpldm/transport/mctp-demux.h>
Patrick Williams05e95592021-09-02 09:28:14 -050012
13#include <sdbusplus/bus/match.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -060014#include <sdeventplus/event.hpp>
15#include <sdeventplus/utility/timer.hpp>
Patrick Williams05e95592021-09-02 09:28:14 -050016
17namespace pldm
18{
19
20namespace MatchRules = sdbusplus::bus::match::rules;
Chris Cainbae4d072022-02-28 09:46:50 -060021using namespace open_power::occ;
Patrick Williams05e95592021-09-02 09:28:14 -050022
23using CompositeEffecterCount = uint8_t;
24using EffecterID = uint16_t;
25using EntityType = uint16_t;
26using EntityInstance = uint16_t;
27using EventState = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050028using InstanceToEffecter = std::map<open_power::occ::instanceID, EffecterID>;
Patrick Williams05e95592021-09-02 09:28:14 -050029using PdrList = std::vector<std::vector<uint8_t>>;
30using SensorID = uint16_t;
31using SensorOffset = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050032using SensorToInstance = std::map<SensorID, open_power::occ::instanceID>;
Patrick Williams05e95592021-09-02 09:28:14 -050033using TerminusID = uint8_t;
34
Patrick Williams05e95592021-09-02 09:28:14 -050035/** @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
Rashmica Gupta52328cb2023-02-15 10:38:16 +110041/** @brief Hardcoded TID */
42constexpr TerminusID tid = mctpEid;
43
Patrick Williams05e95592021-09-02 09:28:14 -050044/** @class Interface
45 *
46 * @brief Abstracts the PLDM details related to the OCC
47 */
48class Interface
49{
50 public:
51 Interface() = delete;
Rashmica Guptadb38e912023-05-25 10:33:46 +100052 //~Interface() = default;
Patrick Williams05e95592021-09-02 09:28:14 -050053 Interface(const Interface&) = delete;
54 Interface& operator=(const Interface&) = delete;
55 Interface(Interface&&) = delete;
56 Interface& operator=(Interface&&) = delete;
57
58 /** @brief Constructs the PLDM Interface object for OCC functions
59 *
60 * @param[in] callBack - callBack handler to invoke when the OCC state
61 * changes.
62 */
63 explicit Interface(
Eddie Jamescbad2192021-10-07 09:39:39 -050064 std::function<bool(open_power::occ::instanceID, bool)> callBack,
Chris Cainbae4d072022-02-28 09:46:50 -060065 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack,
Sheldon Bailey31a2f132022-05-20 11:31:52 -050066 std::function<void(bool)> safeModeCallBack, EventPtr& event) :
Patrick Williamsd7542c82024-08-16 15:20:28 -040067 callBack(callBack), sbeCallBack(sbeCallBack),
68 safeModeCallBack(safeModeCallBack), event(event),
Patrick Williams05e95592021-09-02 09:28:14 -050069 pldmEventSignal(
70 open_power::occ::utils::getBus(),
71 MatchRules::type::signal() +
72 MatchRules::member("StateSensorEvent") +
73 MatchRules::path("/xyz/openbmc_project/pldm") +
74 MatchRules::interface("xyz.openbmc_project.PLDM.Event"),
75 std::bind(std::mem_fn(&Interface::sensorEvent), this,
76 std::placeholders::_1)),
Chris Cain157467d2022-06-24 11:25:23 -050077 hostStateSignal(
78 open_power::occ::utils::getBus(),
79 MatchRules::propertiesChanged("/xyz/openbmc_project/state/host0",
80 "xyz.openbmc_project.State.Host"),
81 std::bind(std::mem_fn(&Interface::hostStateEvent), this,
82 std::placeholders::_1)),
Chris Cainbae4d072022-02-28 09:46:50 -060083 sdpEvent(sdeventplus::Event::get_default()),
84 pldmRspTimer(
85 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>(
86 sdpEvent, std::bind(&Interface::pldmRspExpired, this)))
Rashmica Guptadb38e912023-05-25 10:33:46 +100087 {
88 int rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
89 if (rc)
90 {
91 throw std::system_category().default_error_condition(rc);
92 }
93 }
94
95 ~Interface()
96 {
97 int rc = pldm_instance_db_destroy(pldmInstanceIdDb);
98 if (rc)
99 {
100 std::cout << "pldm_instance_db_destroy failed, rc =" << rc << "\n";
101 }
102 }
Patrick Williams05e95592021-09-02 09:28:14 -0500103
Eddie Jamescbad2192021-10-07 09:39:39 -0500104 /** @brief Fetch the state sensor PDRs and populate the cache with
105 * sensorId to OCC/SBE instance mapping information and the sensor
106 * offset for the relevent state set.
Patrick Williams05e95592021-09-02 09:28:14 -0500107 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500108 * @param[in] stateSetId - the state set ID to look for
109 * @param[out] sensorInstanceMap - map of sensorID to instance
Patrick Williams05e95592021-09-02 09:28:14 -0500110 * @param[out] sensorOffset - sensor offset of interested state set ID
111 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500112 void fetchSensorInfo(uint16_t stateSetId,
113 SensorToInstance& sensorInstanceMap,
114 SensorOffset& sensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500115
Eddie Jamescbad2192021-10-07 09:39:39 -0500116 /** @brief Fetch the OCC/SBE state effecter PDRs and populate the cache
117 * with OCC/SBE instance to EffecterID information.
Patrick Williams05e95592021-09-02 09:28:14 -0500118 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500119 * @param[in] stateSetId - the state set ID to look for
120 * @param[out] instanceToEffecterMap - map of instance to effecterID
Patrick Williams05e95592021-09-02 09:28:14 -0500121 * @param[out] count - sensor offset of interested state set ID
Eddie Jamescbad2192021-10-07 09:39:39 -0500122 * @param[out] stateIdPos - position of the stateSetID
Patrick Williams05e95592021-09-02 09:28:14 -0500123 */
Eddie James432dc482021-11-19 15:29:31 -0600124 void fetchEffecterInfo(uint16_t stateSetId,
Eddie Jamescbad2192021-10-07 09:39:39 -0500125 InstanceToEffecter& instanceToEffecterMap,
126 CompositeEffecterCount& count, uint8_t& stateIdPos);
Patrick Williams05e95592021-09-02 09:28:14 -0500127
128 /** @brief Prepare the request for SetStateEffecterStates command
129 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500130 * @param[in] effecterId - the instance effecter ID
131 * @param[in] effecterCount - compositeEffecterCount for the effecter PDR
132 * @param[in] stateIdPos - position of the stateSetID
133 * @param[in] stateSetValue - the value to set the state set to
Patrick Williams05e95592021-09-02 09:28:14 -0500134 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500135 * @return PLDM request message to be sent to host for OCC reset or SBE
136 * HRESET, empty response in the case of failure.
Patrick Williams05e95592021-09-02 09:28:14 -0500137 */
Patrick Williamsd7542c82024-08-16 15:20:28 -0400138 std::vector<uint8_t> prepareSetEffecterReq(
139 EffecterID effecterId, CompositeEffecterCount effecterCount,
140 uint8_t stateIdPos, uint8_t stateSetValue);
Patrick Williams05e95592021-09-02 09:28:14 -0500141
142 /** @brief Send the PLDM message to reset the OCC
143 *
144 * @param[in] instanceId - OCC instance to reset
145 *
146 */
147 void resetOCC(open_power::occ::instanceID occInstanceId);
148
Eddie Jamescbad2192021-10-07 09:39:39 -0500149 /** @brief Send the PLDM message to perform the HRESET
150 *
151 * @param[in] instanceID - SBE instance to HRESET
152 */
153 void sendHRESET(open_power::occ::instanceID sbeInstanceId);
154
Chris Cainbae4d072022-02-28 09:46:50 -0600155 /** @brief Check if the OCC active sensor is available
156 * On successful read, the Manager callback will be called to update
157 * the status
158 *
159 * @param[in] instance - OCC instance to check
160 */
161 void checkActiveSensor(uint8_t instance);
162
Chris Cain755af102024-02-27 16:09:51 -0600163 /** @brief Set the throttleTraces flag
164 *
165 * @param[in] throttle - Flag to indicate if traces should be throttled
166 */
167 void setTraceThrottle(const bool throttle);
168
Patrick Williams05e95592021-09-02 09:28:14 -0500169 private:
Rashmica Guptadb38e912023-05-25 10:33:46 +1000170 /** @brief PLDM instance ID database object used to get instance IDs
171 */
172 pldm_instance_db* pldmInstanceIdDb = nullptr;
173
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100174 /** @brief PLDM instance number used in PLDM requests
Chris Cain8b508bf2022-05-26 14:01:31 -0500175 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100176 std::optional<uint8_t> pldmInstanceID;
Chris Cain8b508bf2022-05-26 14:01:31 -0500177
Patrick Williams05e95592021-09-02 09:28:14 -0500178 /** @brief Callback handler to be invoked when the state of the OCC
179 * changes
180 */
181 std::function<bool(open_power::occ::instanceID, bool)> callBack = nullptr;
182
Eddie Jamescbad2192021-10-07 09:39:39 -0500183 /** @brief Callback handler to be invoked when the maintenance state of the
184 * SBE changes
185 */
186 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack =
187 nullptr;
188
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500189 /** @brief Callback handler to be invoked when the OCC is in SAFE Mode =
190 * true or when OCCs are in_service = false.
191 */
192 std::function<void(bool)> safeModeCallBack = nullptr;
193
Chris Cainbae4d072022-02-28 09:46:50 -0600194 /** @brief reference to sd_event wrapped in unique_ptr */
195 EventPtr& event;
196
197 /** @brief event source wrapped in unique_ptr */
198 EventSourcePtr eventSource;
199
Patrick Williams05e95592021-09-02 09:28:14 -0500200 /** @brief Used to subscribe to D-Bus PLDM StateSensorEvent signal and
201 * processes if the event corresponds to OCC state change.
202 */
203 sdbusplus::bus::match_t pldmEventSignal;
204
Chris Cain157467d2022-06-24 11:25:23 -0500205 /** @brief Used to subscribe for host state change signal */
206 sdbusplus::bus::match_t hostStateSignal;
207
Patrick Williams05e95592021-09-02 09:28:14 -0500208 /** @brief PLDM Sensor ID to OCC Instance mapping
209 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500210 SensorToInstance sensorToOCCInstance;
Patrick Williams05e95592021-09-02 09:28:14 -0500211
Eddie Jamescbad2192021-10-07 09:39:39 -0500212 /** @brief PLDM Sensor ID to SBE Instance mapping
213 */
214 SensorToInstance sensorToSBEInstance;
215
216 /** @brief Sensor offset of OCC state set ID
Patrick Williams05e95592021-09-02 09:28:14 -0500217 * PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS in state sensor PDR.
218 */
George Liuf3a4a692021-12-28 13:59:51 +0800219 SensorOffset OCCSensorOffset = 0;
Eddie Jamescbad2192021-10-07 09:39:39 -0500220
221 /** @brief Sensor offset of the SBE state set ID
222 * PLDM_OEM_IBM_SBE_HRESET_STATE in state sensor PDR.
223 */
George Liuf3a4a692021-12-28 13:59:51 +0800224 SensorOffset SBESensorOffset = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500225
226 /** @brief OCC Instance mapping to PLDM Effecter ID
227 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500228 InstanceToEffecter occInstanceToEffecter;
229
230 /** @brief SBE instance mapping to PLDM Effecter ID
231 */
232 InstanceToEffecter sbeInstanceToEffecter;
Patrick Williams05e95592021-09-02 09:28:14 -0500233
234 /** @brief compositeEffecterCount for OCC reset state effecter PDR */
Eddie Jamescbad2192021-10-07 09:39:39 -0500235 CompositeEffecterCount OCCEffecterCount = 0;
236
237 /** @brief compositeEffecterCount for SBE HRESET state effecter PDR */
238 CompositeEffecterCount SBEEffecterCount = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500239
240 /** @brief Position of Boot/Restart Cause stateSetID in OCC state
241 * effecter PDR
242 */
243 uint8_t bootRestartPosition = 0;
244
Eddie Jamescbad2192021-10-07 09:39:39 -0500245 /** @brief Position of the SBE maintenance stateSetID in the state
246 * effecter PDR
247 */
248 uint8_t sbeMaintenanceStatePosition = 0;
249
Chris Cainbae4d072022-02-28 09:46:50 -0600250 /** @brief OCC instance number for the PLDM message */
251 uint8_t pldmResponseOcc = 0;
252
253 /** @brief File descriptor for PLDM messages */
254 int pldmFd = -1;
255
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100256 /** pldm transport instance */
257 struct pldm_transport* pldmTransport = NULL;
258
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500259 union TransportImpl
260 {
261 struct pldm_transport_mctp_demux* mctpDemux;
262 struct pldm_transport_af_mctp* afMctp;
263 };
264
265 TransportImpl impl;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100266
Chris Cainbae4d072022-02-28 09:46:50 -0600267 /** @brief The response for the PLDM request msg is received flag.
268 */
269 bool pldmResponseReceived = false;
270
271 /** @brief The response for the PLDM request has timed out.
272 */
273 bool pldmResponseTimeout = false;
274
275 /** @brief timer event */
276 sdeventplus::Event sdpEvent;
277
278 /** @brief Timer that is started when PLDM command is sent
279 */
280 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pldmRspTimer;
281
Chris Cain12d0b822022-04-22 17:29:18 -0500282 std::set<uint8_t> outstandingHResets;
283
Chris Cain755af102024-02-27 16:09:51 -0600284 /** @brief Flag to indicate that traces should be throttled.
285 Used to limit traces when there are issues getting OCC status.
286 */
287 static bool throttleTraces;
288
Chris Cainbae4d072022-02-28 09:46:50 -0600289 /** @brief Callback when PLDM response has not been received within the
290 * timeout period.
291 */
292 void pldmRspExpired();
293
294 /** @brief Close the MCTP file */
295 void pldmClose();
296
Patrick Williams05e95592021-09-02 09:28:14 -0500297 /** @brief When the OCC state changes host sends PlatformEventMessage
298 * StateSensorEvent, this function processes the D-Bus signal
299 * with the sensor event information and invokes the callback
300 * to change the OCC state.
301 *
302 * @param[in] msg - data associated with the subscribed signal
303 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500304 void sensorEvent(sdbusplus::message_t& msg);
Patrick Williams05e95592021-09-02 09:28:14 -0500305
Chris Cain157467d2022-06-24 11:25:23 -0500306 /** @brief When the host state changes and if the CurrentHostState is
307 * xyz.openbmc_project.State.Host.HostState.Off then
308 * the cache of OCC sensors and effecters mapping is cleared.
309 *
310 * @param[in] msg - data associated with the subscribed signal
311 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500312 void hostStateEvent(sdbusplus::message_t& msg);
Chris Cain157467d2022-06-24 11:25:23 -0500313
Chris Cainbae4d072022-02-28 09:46:50 -0600314 /** @brief Called when it is determined that the Host is not running.
315 * The cache of OCC sensors and effecters mapping is cleared.
316 */
317 void clearData();
318
Patrick Williams05e95592021-09-02 09:28:14 -0500319 /** @brief Check if the PDR cache for PLDM OCC sensors is valid
320 *
321 * @return true if cache is populated and false if the cache is not
322 * populated.
323 */
324 auto isOCCSensorCacheValid()
325 {
326 return (sensorToOCCInstance.empty() ? false : true);
327 }
328
329 /** @brief Check if the PDR cache for PLDM OCC effecters is valid
330 *
331 * @return true if cache is populated and false if the cache is not
332 * populated.
333 */
334 auto isPDREffecterCacheValid()
335 {
336 return (occInstanceToEffecter.empty() ? false : true);
337 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500338
Rashmica Guptadb38e912023-05-25 10:33:46 +1000339 /** @brief Get a PLDM requester instance id
Eddie Jamescbad2192021-10-07 09:39:39 -0500340 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500341 * @return true if the id was found and false if not
342 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100343 bool getPldmInstanceId();
Eddie Jamescbad2192021-10-07 09:39:39 -0500344
Rashmica Guptadb38e912023-05-25 10:33:46 +1000345 /** @brief Free PLDM requester instance id */
346 void freePldmInstanceId();
347
Chris Cainbae4d072022-02-28 09:46:50 -0600348 /** @brief Encode a GetStateSensor command into a PLDM request
349 * @param[in] instance - OCC instance number
350 * @param[in] sensorId - OCC Active sensor ID number
351 *
352 * @return request - The encoded PLDM messsage to be sent
353 */
Patrick Williamsd7542c82024-08-16 15:20:28 -0400354 std::vector<uint8_t>
355 encodeGetStateSensorRequest(uint8_t instance, uint16_t sensorId);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100356
357 /** @brief setup PLDM transport for sending and receiving PLDM messages.
358 *
359 * @return true on success, otherwise return false
360 */
361 int pldmOpen(void);
362
363 /** @brief Opens the MCTP socket for sending and receiving messages.
364 *
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500365 * @return 0 on success, otherwise returns a negative error code
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100366 */
367 int openMctpDemuxTransport();
368
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500369 /** @brief Opens the MCTP AF_MCTP for sending and receiving messages.
370 *
371 * @return 0 on success, otherwise returns a negative error code
372 */
373 int openAfMctpTransport();
374
Eddie Jamescbad2192021-10-07 09:39:39 -0500375 /** @brief Send the PLDM request
376 *
Chris Caind1b68262022-02-28 09:56:50 -0600377 * @param[in] request - the request data
Chris Cainbae4d072022-02-28 09:46:50 -0600378 * @param[in] rspExpected - false: no need to wait for the response
379 * true: will need to process response in callback
Eddie Jamescbad2192021-10-07 09:39:39 -0500380 */
Chris Cainbae4d072022-02-28 09:46:50 -0600381 void sendPldm(const std::vector<uint8_t>& request, const uint8_t instance,
382 const bool rspExpected = false);
383
384 /** @brief Register a callback function to handle the PLDM response */
385 void registerPldmRspCallback();
386
387 /** @brief callback for the PLDM response event
388 *
389 * @param[in] es - Populated event source
390 * @param[in] fd - Associated File descriptor
391 * @param[in] revents - Type of event
392 * @param[in] userData - User data that was passed during registration
393 *
394 * @return - 0 or positive number on success and negative
395 * errno otherwise
396 */
397 static int pldmRspCallback(sd_event_source* es, int fd, uint32_t revents,
398 void* userData);
Patrick Williams05e95592021-09-02 09:28:14 -0500399};
400
401} // namespace pldm