blob: 0ba1067200e822c642fe85fa5d8c5fdb6166ca57 [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
Chris Cainf0295f52024-09-12 15:41:14 -050017enum pldm_msg_type
18{
19 MSG_UNDEFINED = 0,
20 MSG_SENSOR_STATUS = 1,
21 MSG_OCC_RESET = 2,
22 MSG_HRESET = 3
23};
24
Patrick Williams05e95592021-09-02 09:28:14 -050025namespace pldm
26{
27
28namespace MatchRules = sdbusplus::bus::match::rules;
Chris Cainbae4d072022-02-28 09:46:50 -060029using namespace open_power::occ;
Patrick Williams05e95592021-09-02 09:28:14 -050030
31using CompositeEffecterCount = uint8_t;
32using EffecterID = uint16_t;
33using EntityType = uint16_t;
34using EntityInstance = uint16_t;
35using EventState = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050036using InstanceToEffecter = std::map<open_power::occ::instanceID, EffecterID>;
Patrick Williams05e95592021-09-02 09:28:14 -050037using PdrList = std::vector<std::vector<uint8_t>>;
38using SensorID = uint16_t;
39using SensorOffset = uint8_t;
Eddie Jamescbad2192021-10-07 09:39:39 -050040using SensorToInstance = std::map<SensorID, open_power::occ::instanceID>;
Patrick Williams05e95592021-09-02 09:28:14 -050041using TerminusID = uint8_t;
42
Patrick Williams05e95592021-09-02 09:28:14 -050043/** @brief OCC instance starts with 0 for example "occ0" */
44constexpr open_power::occ::instanceID start = 0;
45
46/** @brief Hardcoded mctpEid for HBRT */
47constexpr mctp_eid_t mctpEid = 10;
48
Rashmica Gupta52328cb2023-02-15 10:38:16 +110049/** @brief Hardcoded TID */
50constexpr TerminusID tid = mctpEid;
51
Patrick Williams05e95592021-09-02 09:28:14 -050052/** @class Interface
53 *
54 * @brief Abstracts the PLDM details related to the OCC
55 */
56class Interface
57{
58 public:
59 Interface() = delete;
Rashmica Guptadb38e912023-05-25 10:33:46 +100060 //~Interface() = default;
Patrick Williams05e95592021-09-02 09:28:14 -050061 Interface(const Interface&) = delete;
62 Interface& operator=(const Interface&) = delete;
63 Interface(Interface&&) = delete;
64 Interface& operator=(Interface&&) = delete;
65
66 /** @brief Constructs the PLDM Interface object for OCC functions
67 *
Chris Cainf0295f52024-09-12 15:41:14 -050068 * @param[in] occActiveCallBack - callBack handler to invoke when the OCC
69 * state changes.
70 * @param[in] sbeCallBack - callBack handler to invoke when the SBE
71 * state changes.
72 * @param[in] safeModeCallBack - callBack handler to invoke when the
73 * system is in safe mode.
Chris Cainc488bac2025-03-17 09:01:15 -050074 * @param[in] poweredOffCallBack - callBack handler to invoke when the
75 * host is powered off.
Patrick Williams05e95592021-09-02 09:28:14 -050076 */
77 explicit Interface(
Chris Cainf0295f52024-09-12 15:41:14 -050078 std::function<bool(open_power::occ::instanceID, bool)>
79 occActiveCallBack,
Chris Cainbae4d072022-02-28 09:46:50 -060080 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack,
Chris Cainc488bac2025-03-17 09:01:15 -050081 std::function<void(bool)> safeModeCallBack,
82 std::function<void()> poweredOffCallBack, EventPtr& event) :
Chris Cainf0295f52024-09-12 15:41:14 -050083 occActiveCallBack(occActiveCallBack), sbeCallBack(sbeCallBack),
Chris Cainc488bac2025-03-17 09:01:15 -050084 safeModeCallBack(safeModeCallBack),
85 poweredOffCallBack(poweredOffCallBack), event(event),
Patrick Williams05e95592021-09-02 09:28:14 -050086 pldmEventSignal(
87 open_power::occ::utils::getBus(),
88 MatchRules::type::signal() +
89 MatchRules::member("StateSensorEvent") +
90 MatchRules::path("/xyz/openbmc_project/pldm") +
91 MatchRules::interface("xyz.openbmc_project.PLDM.Event"),
92 std::bind(std::mem_fn(&Interface::sensorEvent), this,
93 std::placeholders::_1)),
Chris Cain157467d2022-06-24 11:25:23 -050094 hostStateSignal(
95 open_power::occ::utils::getBus(),
96 MatchRules::propertiesChanged("/xyz/openbmc_project/state/host0",
97 "xyz.openbmc_project.State.Host"),
98 std::bind(std::mem_fn(&Interface::hostStateEvent), this,
99 std::placeholders::_1)),
Chris Cainbae4d072022-02-28 09:46:50 -0600100 sdpEvent(sdeventplus::Event::get_default()),
101 pldmRspTimer(
102 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>(
103 sdpEvent, std::bind(&Interface::pldmRspExpired, this)))
Rashmica Guptadb38e912023-05-25 10:33:46 +1000104 {
105 int rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
106 if (rc)
107 {
108 throw std::system_category().default_error_condition(rc);
109 }
110 }
111
112 ~Interface()
113 {
114 int rc = pldm_instance_db_destroy(pldmInstanceIdDb);
115 if (rc)
116 {
117 std::cout << "pldm_instance_db_destroy failed, rc =" << rc << "\n";
118 }
119 }
Patrick Williams05e95592021-09-02 09:28:14 -0500120
Eddie Jamescbad2192021-10-07 09:39:39 -0500121 /** @brief Fetch the state sensor PDRs and populate the cache with
122 * sensorId to OCC/SBE instance mapping information and the sensor
123 * offset for the relevent state set.
Patrick Williams05e95592021-09-02 09:28:14 -0500124 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500125 * @param[in] stateSetId - the state set ID to look for
126 * @param[out] sensorInstanceMap - map of sensorID to instance
Patrick Williams05e95592021-09-02 09:28:14 -0500127 * @param[out] sensorOffset - sensor offset of interested state set ID
128 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500129 void fetchSensorInfo(uint16_t stateSetId,
130 SensorToInstance& sensorInstanceMap,
131 SensorOffset& sensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500132
Eddie Jamescbad2192021-10-07 09:39:39 -0500133 /** @brief Fetch the OCC/SBE state effecter PDRs and populate the cache
134 * with OCC/SBE instance to EffecterID information.
Patrick Williams05e95592021-09-02 09:28:14 -0500135 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500136 * @param[in] stateSetId - the state set ID to look for
137 * @param[out] instanceToEffecterMap - map of instance to effecterID
Patrick Williams05e95592021-09-02 09:28:14 -0500138 * @param[out] count - sensor offset of interested state set ID
Eddie Jamescbad2192021-10-07 09:39:39 -0500139 * @param[out] stateIdPos - position of the stateSetID
Patrick Williams05e95592021-09-02 09:28:14 -0500140 */
Eddie James432dc482021-11-19 15:29:31 -0600141 void fetchEffecterInfo(uint16_t stateSetId,
Eddie Jamescbad2192021-10-07 09:39:39 -0500142 InstanceToEffecter& instanceToEffecterMap,
143 CompositeEffecterCount& count, uint8_t& stateIdPos);
Patrick Williams05e95592021-09-02 09:28:14 -0500144
145 /** @brief Prepare the request for SetStateEffecterStates command
146 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500147 * @param[in] effecterId - the instance effecter ID
148 * @param[in] effecterCount - compositeEffecterCount for the effecter PDR
149 * @param[in] stateIdPos - position of the stateSetID
150 * @param[in] stateSetValue - the value to set the state set to
Patrick Williams05e95592021-09-02 09:28:14 -0500151 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500152 * @return PLDM request message to be sent to host for OCC reset or SBE
153 * HRESET, empty response in the case of failure.
Patrick Williams05e95592021-09-02 09:28:14 -0500154 */
Patrick Williamsd7542c82024-08-16 15:20:28 -0400155 std::vector<uint8_t> prepareSetEffecterReq(
156 EffecterID effecterId, CompositeEffecterCount effecterCount,
157 uint8_t stateIdPos, uint8_t stateSetValue);
Patrick Williams05e95592021-09-02 09:28:14 -0500158
159 /** @brief Send the PLDM message to reset the OCC
160 *
161 * @param[in] instanceId - OCC instance to reset
162 *
163 */
164 void resetOCC(open_power::occ::instanceID occInstanceId);
165
Eddie Jamescbad2192021-10-07 09:39:39 -0500166 /** @brief Send the PLDM message to perform the HRESET
167 *
168 * @param[in] instanceID - SBE instance to HRESET
169 */
170 void sendHRESET(open_power::occ::instanceID sbeInstanceId);
171
Chris Cainbae4d072022-02-28 09:46:50 -0600172 /** @brief Check if the OCC active sensor is available
173 * On successful read, the Manager callback will be called to update
174 * the status
175 *
176 * @param[in] instance - OCC instance to check
177 */
178 void checkActiveSensor(uint8_t instance);
179
Chris Cain755af102024-02-27 16:09:51 -0600180 /** @brief Set the throttleTraces flag
181 *
182 * @param[in] throttle - Flag to indicate if traces should be throttled
183 */
184 void setTraceThrottle(const bool throttle);
185
Patrick Williams05e95592021-09-02 09:28:14 -0500186 private:
Rashmica Guptadb38e912023-05-25 10:33:46 +1000187 /** @brief PLDM instance ID database object used to get instance IDs
188 */
189 pldm_instance_db* pldmInstanceIdDb = nullptr;
190
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100191 /** @brief PLDM instance number used in PLDM requests
Chris Cain8b508bf2022-05-26 14:01:31 -0500192 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100193 std::optional<uint8_t> pldmInstanceID;
Chris Cain8b508bf2022-05-26 14:01:31 -0500194
Patrick Williams05e95592021-09-02 09:28:14 -0500195 /** @brief Callback handler to be invoked when the state of the OCC
196 * changes
197 */
Chris Cainf0295f52024-09-12 15:41:14 -0500198 std::function<bool(open_power::occ::instanceID, bool)> occActiveCallBack =
199 nullptr;
Patrick Williams05e95592021-09-02 09:28:14 -0500200
Eddie Jamescbad2192021-10-07 09:39:39 -0500201 /** @brief Callback handler to be invoked when the maintenance state of the
202 * SBE changes
203 */
204 std::function<void(open_power::occ::instanceID, bool)> sbeCallBack =
205 nullptr;
206
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500207 /** @brief Callback handler to be invoked when the OCC is in SAFE Mode =
208 * true or when OCCs are in_service = false.
209 */
210 std::function<void(bool)> safeModeCallBack = nullptr;
211
Chris Cainc488bac2025-03-17 09:01:15 -0500212 /** @brief Callback handler to be invoked when the host is powered off */
213 std::function<void()> poweredOffCallBack = nullptr;
214
Chris Cainbae4d072022-02-28 09:46:50 -0600215 /** @brief reference to sd_event wrapped in unique_ptr */
216 EventPtr& event;
217
218 /** @brief event source wrapped in unique_ptr */
219 EventSourcePtr eventSource;
220
Patrick Williams05e95592021-09-02 09:28:14 -0500221 /** @brief Used to subscribe to D-Bus PLDM StateSensorEvent signal and
222 * processes if the event corresponds to OCC state change.
223 */
224 sdbusplus::bus::match_t pldmEventSignal;
225
Chris Cain157467d2022-06-24 11:25:23 -0500226 /** @brief Used to subscribe for host state change signal */
227 sdbusplus::bus::match_t hostStateSignal;
228
Patrick Williams05e95592021-09-02 09:28:14 -0500229 /** @brief PLDM Sensor ID to OCC Instance mapping
230 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500231 SensorToInstance sensorToOCCInstance;
Patrick Williams05e95592021-09-02 09:28:14 -0500232
Eddie Jamescbad2192021-10-07 09:39:39 -0500233 /** @brief PLDM Sensor ID to SBE Instance mapping
234 */
235 SensorToInstance sensorToSBEInstance;
236
237 /** @brief Sensor offset of OCC state set ID
Patrick Williams05e95592021-09-02 09:28:14 -0500238 * PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS in state sensor PDR.
239 */
George Liuf3a4a692021-12-28 13:59:51 +0800240 SensorOffset OCCSensorOffset = 0;
Eddie Jamescbad2192021-10-07 09:39:39 -0500241
242 /** @brief Sensor offset of the SBE state set ID
243 * PLDM_OEM_IBM_SBE_HRESET_STATE in state sensor PDR.
244 */
George Liuf3a4a692021-12-28 13:59:51 +0800245 SensorOffset SBESensorOffset = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500246
247 /** @brief OCC Instance mapping to PLDM Effecter ID
248 */
Eddie Jamescbad2192021-10-07 09:39:39 -0500249 InstanceToEffecter occInstanceToEffecter;
250
251 /** @brief SBE instance mapping to PLDM Effecter ID
252 */
253 InstanceToEffecter sbeInstanceToEffecter;
Patrick Williams05e95592021-09-02 09:28:14 -0500254
255 /** @brief compositeEffecterCount for OCC reset state effecter PDR */
Eddie Jamescbad2192021-10-07 09:39:39 -0500256 CompositeEffecterCount OCCEffecterCount = 0;
257
258 /** @brief compositeEffecterCount for SBE HRESET state effecter PDR */
259 CompositeEffecterCount SBEEffecterCount = 0;
Patrick Williams05e95592021-09-02 09:28:14 -0500260
261 /** @brief Position of Boot/Restart Cause stateSetID in OCC state
262 * effecter PDR
263 */
264 uint8_t bootRestartPosition = 0;
265
Eddie Jamescbad2192021-10-07 09:39:39 -0500266 /** @brief Position of the SBE maintenance stateSetID in the state
267 * effecter PDR
268 */
269 uint8_t sbeMaintenanceStatePosition = 0;
270
Chris Cainbae4d072022-02-28 09:46:50 -0600271 /** @brief OCC instance number for the PLDM message */
272 uint8_t pldmResponseOcc = 0;
273
274 /** @brief File descriptor for PLDM messages */
275 int pldmFd = -1;
276
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100277 /** pldm transport instance */
278 struct pldm_transport* pldmTransport = NULL;
279
Chris Cainf0295f52024-09-12 15:41:14 -0500280 static enum pldm_msg_type msgType;
281
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500282 union TransportImpl
283 {
284 struct pldm_transport_mctp_demux* mctpDemux;
285 struct pldm_transport_af_mctp* afMctp;
286 };
287
288 TransportImpl impl;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100289
Chris Cainee364512025-04-16 16:08:34 -0500290 /**
291 * @brief The header for the most recent request.
292 */
293 pldm_msg_hdr _requestHeader{};
294
Chris Cainbae4d072022-02-28 09:46:50 -0600295 /** @brief The response for the PLDM request msg is received flag.
296 */
297 bool pldmResponseReceived = false;
298
299 /** @brief The response for the PLDM request has timed out.
300 */
301 bool pldmResponseTimeout = false;
302
Chris Cainf0295f52024-09-12 15:41:14 -0500303 /** @brief The instance ID for the OCC/HRESET request */
304 static open_power::occ::instanceID resetInstance;
305
Chris Cainbae4d072022-02-28 09:46:50 -0600306 /** @brief timer event */
307 sdeventplus::Event sdpEvent;
308
309 /** @brief Timer that is started when PLDM command is sent
310 */
311 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pldmRspTimer;
312
Chris Cain12d0b822022-04-22 17:29:18 -0500313 std::set<uint8_t> outstandingHResets;
314
Chris Cain755af102024-02-27 16:09:51 -0600315 /** @brief Flag to indicate that traces should be throttled.
316 Used to limit traces when there are issues getting OCC status.
317 */
318 static bool throttleTraces;
319
Chris Cainbae4d072022-02-28 09:46:50 -0600320 /** @brief Callback when PLDM response has not been received within the
321 * timeout period.
322 */
323 void pldmRspExpired();
324
325 /** @brief Close the MCTP file */
326 void pldmClose();
327
Patrick Williams05e95592021-09-02 09:28:14 -0500328 /** @brief When the OCC state changes host sends PlatformEventMessage
329 * StateSensorEvent, this function processes the D-Bus signal
330 * with the sensor event information and invokes the callback
331 * to change the OCC state.
332 *
333 * @param[in] msg - data associated with the subscribed signal
334 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500335 void sensorEvent(sdbusplus::message_t& msg);
Patrick Williams05e95592021-09-02 09:28:14 -0500336
Chris Cain157467d2022-06-24 11:25:23 -0500337 /** @brief When the host state changes and if the CurrentHostState is
338 * xyz.openbmc_project.State.Host.HostState.Off then
339 * the cache of OCC sensors and effecters mapping is cleared.
340 *
341 * @param[in] msg - data associated with the subscribed signal
342 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500343 void hostStateEvent(sdbusplus::message_t& msg);
Chris Cain157467d2022-06-24 11:25:23 -0500344
Chris Cainbae4d072022-02-28 09:46:50 -0600345 /** @brief Called when it is determined that the Host is not running.
346 * The cache of OCC sensors and effecters mapping is cleared.
347 */
348 void clearData();
349
Patrick Williams05e95592021-09-02 09:28:14 -0500350 /** @brief Check if the PDR cache for PLDM OCC sensors is valid
351 *
352 * @return true if cache is populated and false if the cache is not
353 * populated.
354 */
355 auto isOCCSensorCacheValid()
356 {
357 return (sensorToOCCInstance.empty() ? false : true);
358 }
359
360 /** @brief Check if the PDR cache for PLDM OCC effecters is valid
361 *
362 * @return true if cache is populated and false if the cache is not
363 * populated.
364 */
365 auto isPDREffecterCacheValid()
366 {
367 return (occInstanceToEffecter.empty() ? false : true);
368 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500369
Rashmica Guptadb38e912023-05-25 10:33:46 +1000370 /** @brief Get a PLDM requester instance id
Eddie Jamescbad2192021-10-07 09:39:39 -0500371 *
Eddie Jamescbad2192021-10-07 09:39:39 -0500372 * @return true if the id was found and false if not
373 */
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100374 bool getPldmInstanceId();
Eddie Jamescbad2192021-10-07 09:39:39 -0500375
Rashmica Guptadb38e912023-05-25 10:33:46 +1000376 /** @brief Free PLDM requester instance id */
377 void freePldmInstanceId();
378
Chris Cainbae4d072022-02-28 09:46:50 -0600379 /** @brief Encode a GetStateSensor command into a PLDM request
380 * @param[in] instance - OCC instance number
381 * @param[in] sensorId - OCC Active sensor ID number
382 *
383 * @return request - The encoded PLDM messsage to be sent
384 */
Patrick Williams2d6ec902025-02-01 08:22:13 -0500385 std::vector<uint8_t> encodeGetStateSensorRequest(uint8_t instance,
386 uint16_t sensorId);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100387
388 /** @brief setup PLDM transport for sending and receiving PLDM messages.
389 *
390 * @return true on success, otherwise return false
391 */
392 int pldmOpen(void);
393
394 /** @brief Opens the MCTP socket for sending and receiving messages.
395 *
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500396 * @return 0 on success, otherwise returns a negative error code
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100397 */
398 int openMctpDemuxTransport();
399
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500400 /** @brief Opens the MCTP AF_MCTP for sending and receiving messages.
401 *
402 * @return 0 on success, otherwise returns a negative error code
403 */
404 int openAfMctpTransport();
405
Eddie Jamescbad2192021-10-07 09:39:39 -0500406 /** @brief Send the PLDM request
407 *
Chris Caind1b68262022-02-28 09:56:50 -0600408 * @param[in] request - the request data
Chris Cainbae4d072022-02-28 09:46:50 -0600409 * @param[in] rspExpected - false: no need to wait for the response
410 * true: will need to process response in callback
Eddie Jamescbad2192021-10-07 09:39:39 -0500411 */
Chris Cainbae4d072022-02-28 09:46:50 -0600412 void sendPldm(const std::vector<uint8_t>& request, const uint8_t instance,
413 const bool rspExpected = false);
414
415 /** @brief Register a callback function to handle the PLDM response */
416 void registerPldmRspCallback();
417
418 /** @brief callback for the PLDM response event
419 *
420 * @param[in] es - Populated event source
421 * @param[in] fd - Associated File descriptor
422 * @param[in] revents - Type of event
423 * @param[in] userData - User data that was passed during registration
424 *
425 * @return - 0 or positive number on success and negative
426 * errno otherwise
427 */
428 static int pldmRspCallback(sd_event_source* es, int fd, uint32_t revents,
429 void* userData);
Chris Cainf0295f52024-09-12 15:41:14 -0500430
431 /** @brief callback for a OCC / HRESET response event
432 *
433 * @param[in] es - Populated event source
434 * @param[in] fd - Associated File descriptor
435 * @param[in] revents - Type of event
436 * @param[in] userData - User data that was passed during registration
437 *
438 * @return - 0 or positive number on success and negative
439 * errno otherwise
440 */
441 static int pldmResetCallback(sd_event_source* /*es*/,
442 __attribute__((unused)) int fd,
443 uint32_t revents, void* userData);
Patrick Williams05e95592021-09-02 09:28:14 -0500444};
445
446} // namespace pldm
Chris Cainf0295f52024-09-12 15:41:14 -0500447
448template <>
449struct std::formatter<enum pldm_msg_type> : formatter<int>
450{
451 auto format(enum pldm_msg_type m, format_context& ctx) const
452 {
453 return formatter<int>::format(std::to_underlying(m), ctx);
454 }
455};