19b1a0b6bSPavithra Barithaya #include "config.h"
29b1a0b6bSPavithra Barithaya
3a001020fSAndrew Jeffery #include <libpldm/oem/ibm/state_set.h>
4bb90afc7SBen Tyner #include <libpldm/platform.h>
5bb90afc7SBen Tyner #include <libpldm/pldm.h>
69b1a0b6bSPavithra Barithaya #include <libpldm/transport.h>
7*316acdacSPavithra Barithaya #include <libpldm/transport/af-mctp.h>
89b1a0b6bSPavithra Barithaya #include <libpldm/transport/mctp-demux.h>
99b1a0b6bSPavithra Barithaya #include <poll.h>
10bb90afc7SBen Tyner
11bb90afc7SBen Tyner #include <util/dbus.hpp>
1236b043e9SPavithra Barithaya #include <util/pldm.hpp>
13bb90afc7SBen Tyner #include <util/trace.hpp>
14bb90afc7SBen Tyner
15bb90afc7SBen Tyner namespace util
16bb90afc7SBen Tyner {
17bb90afc7SBen Tyner namespace pldm
18bb90afc7SBen Tyner {
1936b043e9SPavithra Barithaya
2036b043e9SPavithra Barithaya class PLDMInstanceManager
2136b043e9SPavithra Barithaya {
2236b043e9SPavithra Barithaya public:
2336b043e9SPavithra Barithaya // Singleton access method
getInstance()2436b043e9SPavithra Barithaya static PLDMInstanceManager& getInstance()
2536b043e9SPavithra Barithaya {
2636b043e9SPavithra Barithaya static PLDMInstanceManager instance;
2736b043e9SPavithra Barithaya return instance;
2836b043e9SPavithra Barithaya }
2936b043e9SPavithra Barithaya
3036b043e9SPavithra Barithaya bool getPldmInstanceID(uint8_t& pldmInstance, uint8_t tid);
3136b043e9SPavithra Barithaya void freePLDMInstanceID(pldm_instance_id_t instanceID, uint8_t tid);
3236b043e9SPavithra Barithaya
339b1a0b6bSPavithra Barithaya /**
349b1a0b6bSPavithra Barithaya * @brief setup PLDM transport for sending and receiving messages
359b1a0b6bSPavithra Barithaya *
369b1a0b6bSPavithra Barithaya * @param[in] eid - MCTP endpoint ID
379b1a0b6bSPavithra Barithaya * @return file descriptor on success and throw
389b1a0b6bSPavithra Barithaya * exception (xyz::openbmc_project::Common::Error::NotAllowed) on
399b1a0b6bSPavithra Barithaya * failures.
409b1a0b6bSPavithra Barithaya */
419b1a0b6bSPavithra Barithaya int openPLDM(mctp_eid_t eid);
429b1a0b6bSPavithra Barithaya /** @brief Opens the MCTP socket for sending and receiving messages.
439b1a0b6bSPavithra Barithaya *
449b1a0b6bSPavithra Barithaya * @param[in] eid - MCTP endpoint ID
459b1a0b6bSPavithra Barithaya */
469b1a0b6bSPavithra Barithaya int openMctpDemuxTransport(mctp_eid_t eid);
479b1a0b6bSPavithra Barithaya
489b1a0b6bSPavithra Barithaya /** @brief Close the PLDM file */
499b1a0b6bSPavithra Barithaya void closePLDM();
509b1a0b6bSPavithra Barithaya
519b1a0b6bSPavithra Barithaya /** @brief sending PLDM file */
529b1a0b6bSPavithra Barithaya bool sendPldm(const std::vector<uint8_t>& request, uint8_t mctpEid);
539b1a0b6bSPavithra Barithaya
54*316acdacSPavithra Barithaya /** @brief Opens the MCTP AF_MCTP for sending and receiving messages.
55*316acdacSPavithra Barithaya *
56*316acdacSPavithra Barithaya * @param[in] eid - MCTP endpoint ID
57*316acdacSPavithra Barithaya */
58*316acdacSPavithra Barithaya int openAfMctpTransport(mctp_eid_t eid);
59*316acdacSPavithra Barithaya
60*316acdacSPavithra Barithaya union TransportImpl
61*316acdacSPavithra Barithaya {
62*316acdacSPavithra Barithaya pldm_transport_mctp_demux* mctpDemux;
63*316acdacSPavithra Barithaya pldm_transport_af_mctp* afMctp;
64*316acdacSPavithra Barithaya };
65*316acdacSPavithra Barithaya
6636b043e9SPavithra Barithaya private:
6736b043e9SPavithra Barithaya // Private constructor and destructor to prevent creating multiple instances
6836b043e9SPavithra Barithaya PLDMInstanceManager();
6936b043e9SPavithra Barithaya ~PLDMInstanceManager();
7036b043e9SPavithra Barithaya
7136b043e9SPavithra Barithaya // Deleted copy constructor and assignment operator to prevent copying
7236b043e9SPavithra Barithaya PLDMInstanceManager(const PLDMInstanceManager&) = delete;
7336b043e9SPavithra Barithaya PLDMInstanceManager& operator=(const PLDMInstanceManager&) = delete;
7436b043e9SPavithra Barithaya
7536b043e9SPavithra Barithaya // Private member for the instance database
7636b043e9SPavithra Barithaya pldm_instance_db* pldmInstanceIdDb;
779b1a0b6bSPavithra Barithaya
789b1a0b6bSPavithra Barithaya /** pldm transport instance */
799b1a0b6bSPavithra Barithaya struct pldm_transport* pldmTransport = NULL;
809b1a0b6bSPavithra Barithaya
81*316acdacSPavithra Barithaya // type of transport implementation instance
82*316acdacSPavithra Barithaya TransportImpl impl;
8336b043e9SPavithra Barithaya };
8436b043e9SPavithra Barithaya
PLDMInstanceManager()8536b043e9SPavithra Barithaya PLDMInstanceManager::PLDMInstanceManager() : pldmInstanceIdDb(nullptr)
8636b043e9SPavithra Barithaya {
8736b043e9SPavithra Barithaya // Initialize the database object directly in the constructor
8836b043e9SPavithra Barithaya auto rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
8936b043e9SPavithra Barithaya if (rc)
9036b043e9SPavithra Barithaya {
9136b043e9SPavithra Barithaya trace::err("Error calling pldm_instance_db_init_default, rc = %d",
9236b043e9SPavithra Barithaya (unsigned)rc);
9336b043e9SPavithra Barithaya }
9436b043e9SPavithra Barithaya }
9536b043e9SPavithra Barithaya
~PLDMInstanceManager()9636b043e9SPavithra Barithaya PLDMInstanceManager::~PLDMInstanceManager()
9736b043e9SPavithra Barithaya {
9836b043e9SPavithra Barithaya // Directly destroy the database object in the destructor
9936b043e9SPavithra Barithaya if (pldmInstanceIdDb)
10036b043e9SPavithra Barithaya {
10136b043e9SPavithra Barithaya auto rc = pldm_instance_db_destroy(pldmInstanceIdDb);
10236b043e9SPavithra Barithaya if (rc)
10336b043e9SPavithra Barithaya {
10436b043e9SPavithra Barithaya trace::err("pldm_instance_db_destroy failed rc = %d", (unsigned)rc);
10536b043e9SPavithra Barithaya }
10636b043e9SPavithra Barithaya }
10736b043e9SPavithra Barithaya }
10836b043e9SPavithra Barithaya
10936b043e9SPavithra Barithaya // Get the PLDM instance ID for the given terminus ID
getPldmInstanceID(uint8_t & pldmInstance,uint8_t tid)11036b043e9SPavithra Barithaya bool PLDMInstanceManager::getPldmInstanceID(uint8_t& pldmInstance, uint8_t tid)
11136b043e9SPavithra Barithaya {
11236b043e9SPavithra Barithaya pldm_instance_id_t id;
11336b043e9SPavithra Barithaya int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
11436b043e9SPavithra Barithaya if (rc == -EAGAIN)
11536b043e9SPavithra Barithaya {
11636b043e9SPavithra Barithaya std::this_thread::sleep_for(
11736b043e9SPavithra Barithaya std::chrono::milliseconds(100)); // Retry after 100ms
11836b043e9SPavithra Barithaya rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid,
11936b043e9SPavithra Barithaya &id); // Retry allocation
12036b043e9SPavithra Barithaya }
12136b043e9SPavithra Barithaya
12236b043e9SPavithra Barithaya if (rc)
12336b043e9SPavithra Barithaya {
12436b043e9SPavithra Barithaya trace::err("getPldmInstanceId: Failed to alloc ID for TID = %d, RC= %d",
12536b043e9SPavithra Barithaya (unsigned)tid, (unsigned)rc);
12636b043e9SPavithra Barithaya return false;
12736b043e9SPavithra Barithaya }
12836b043e9SPavithra Barithaya
12936b043e9SPavithra Barithaya pldmInstance = id; // Return the allocated instance ID
13036b043e9SPavithra Barithaya trace::inf("Got instanceId: %d, for PLDM TID: %d", (unsigned)pldmInstance,
13136b043e9SPavithra Barithaya (unsigned)tid);
13236b043e9SPavithra Barithaya return true;
13336b043e9SPavithra Barithaya }
13436b043e9SPavithra Barithaya
13536b043e9SPavithra Barithaya // Free the PLDM instance ID associated with the terminus ID
freePLDMInstanceID(pldm_instance_id_t instanceID,uint8_t tid)13636b043e9SPavithra Barithaya void PLDMInstanceManager::freePLDMInstanceID(pldm_instance_id_t instanceID,
13736b043e9SPavithra Barithaya uint8_t tid)
13836b043e9SPavithra Barithaya {
13936b043e9SPavithra Barithaya int rc = pldm_instance_id_free(pldmInstanceIdDb, tid, instanceID);
14036b043e9SPavithra Barithaya if (rc)
14136b043e9SPavithra Barithaya {
14236b043e9SPavithra Barithaya trace::err(
14336b043e9SPavithra Barithaya "pldm_instance_id_free failed to free id=%d of TID=%d with rc= %d",
14436b043e9SPavithra Barithaya (unsigned)instanceID, (unsigned)tid, (unsigned)rc);
14536b043e9SPavithra Barithaya }
14636b043e9SPavithra Barithaya }
14736b043e9SPavithra Barithaya
openPLDM(mctp_eid_t eid)1489b1a0b6bSPavithra Barithaya int PLDMInstanceManager::openPLDM(mctp_eid_t eid)
1499b1a0b6bSPavithra Barithaya {
1509b1a0b6bSPavithra Barithaya auto fd = -1;
1519b1a0b6bSPavithra Barithaya if (pldmTransport)
1529b1a0b6bSPavithra Barithaya {
1539b1a0b6bSPavithra Barithaya trace::inf("open: pldmTransport already setup!");
1549b1a0b6bSPavithra Barithaya return fd;
1559b1a0b6bSPavithra Barithaya }
156*316acdacSPavithra Barithaya #if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
1579b1a0b6bSPavithra Barithaya fd = openMctpDemuxTransport(eid);
158*316acdacSPavithra Barithaya #elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
159*316acdacSPavithra Barithaya fd = openAfMctpTransport(eid);
160*316acdacSPavithra Barithaya #else
161*316acdacSPavithra Barithaya trace::err("open: No valid transport defined!");
162*316acdacSPavithra Barithaya #endif
1639b1a0b6bSPavithra Barithaya if (fd < 0)
1649b1a0b6bSPavithra Barithaya {
1659b1a0b6bSPavithra Barithaya auto e = errno;
1669b1a0b6bSPavithra Barithaya trace::err("openPLDM failed, fd = %d and error= %d", (unsigned)fd, e);
1679b1a0b6bSPavithra Barithaya }
1689b1a0b6bSPavithra Barithaya return fd;
1699b1a0b6bSPavithra Barithaya }
1709b1a0b6bSPavithra Barithaya
openMctpDemuxTransport(mctp_eid_t eid)171*316acdacSPavithra Barithaya [[maybe_unused]] int PLDMInstanceManager::openMctpDemuxTransport(mctp_eid_t eid)
1729b1a0b6bSPavithra Barithaya {
173*316acdacSPavithra Barithaya impl.mctpDemux = nullptr;
174*316acdacSPavithra Barithaya int rc = pldm_transport_mctp_demux_init(&impl.mctpDemux);
1759b1a0b6bSPavithra Barithaya if (rc)
1769b1a0b6bSPavithra Barithaya {
1779b1a0b6bSPavithra Barithaya trace::err(
1789b1a0b6bSPavithra Barithaya "openMctpDemuxTransport: Failed to setup tid to eid mapping. rc = %d",
1799b1a0b6bSPavithra Barithaya (unsigned)rc);
1809b1a0b6bSPavithra Barithaya closePLDM();
1819b1a0b6bSPavithra Barithaya return rc;
1829b1a0b6bSPavithra Barithaya }
1839b1a0b6bSPavithra Barithaya
184*316acdacSPavithra Barithaya rc = pldm_transport_mctp_demux_map_tid(impl.mctpDemux, eid, eid);
1859b1a0b6bSPavithra Barithaya if (rc)
1869b1a0b6bSPavithra Barithaya {
1879b1a0b6bSPavithra Barithaya trace::err(
1889b1a0b6bSPavithra Barithaya "openMctpDemuxTransport: Failed to setup tid to eid mapping. rc = %d",
1899b1a0b6bSPavithra Barithaya (unsigned)rc);
1909b1a0b6bSPavithra Barithaya closePLDM();
1919b1a0b6bSPavithra Barithaya return rc;
1929b1a0b6bSPavithra Barithaya }
1939b1a0b6bSPavithra Barithaya
194*316acdacSPavithra Barithaya pldmTransport = pldm_transport_mctp_demux_core(impl.mctpDemux);
1959b1a0b6bSPavithra Barithaya struct pollfd pollfd;
1969b1a0b6bSPavithra Barithaya rc = pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd);
1979b1a0b6bSPavithra Barithaya if (rc)
1989b1a0b6bSPavithra Barithaya {
1999b1a0b6bSPavithra Barithaya trace::err("openMctpDemuxTransport: Failed to get pollfd. rc= %d",
2009b1a0b6bSPavithra Barithaya (unsigned)rc);
2019b1a0b6bSPavithra Barithaya closePLDM();
2029b1a0b6bSPavithra Barithaya return rc;
2039b1a0b6bSPavithra Barithaya }
2049b1a0b6bSPavithra Barithaya return pollfd.fd;
2059b1a0b6bSPavithra Barithaya }
206*316acdacSPavithra Barithaya
openAfMctpTransport(mctp_eid_t eid)207*316acdacSPavithra Barithaya [[maybe_unused]] int PLDMInstanceManager::openAfMctpTransport(mctp_eid_t eid)
208*316acdacSPavithra Barithaya {
209*316acdacSPavithra Barithaya impl.afMctp = nullptr;
210*316acdacSPavithra Barithaya int rc = pldm_transport_af_mctp_init(&impl.afMctp);
211*316acdacSPavithra Barithaya if (rc)
212*316acdacSPavithra Barithaya {
213*316acdacSPavithra Barithaya trace::err(
214*316acdacSPavithra Barithaya "openAfMctpTransport: Failed to init AF MCTP transport. rc = %d",
215*316acdacSPavithra Barithaya (unsigned)rc);
216*316acdacSPavithra Barithaya return rc;
217*316acdacSPavithra Barithaya }
218*316acdacSPavithra Barithaya rc = pldm_transport_af_mctp_map_tid(impl.afMctp, eid, eid);
219*316acdacSPavithra Barithaya if (rc)
220*316acdacSPavithra Barithaya {
221*316acdacSPavithra Barithaya trace::err(
222*316acdacSPavithra Barithaya "openAfMctpTransport: Failed to setup tid to eid mapping. rc = %d",
223*316acdacSPavithra Barithaya (unsigned)rc);
224*316acdacSPavithra Barithaya closePLDM();
225*316acdacSPavithra Barithaya return rc;
226*316acdacSPavithra Barithaya }
227*316acdacSPavithra Barithaya pldmTransport = pldm_transport_af_mctp_core(impl.afMctp);
228*316acdacSPavithra Barithaya struct pollfd pollfd;
229*316acdacSPavithra Barithaya rc = pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd);
230*316acdacSPavithra Barithaya if (rc)
231*316acdacSPavithra Barithaya {
232*316acdacSPavithra Barithaya trace::err("openAfMctpTransport: Failed to get pollfd. rc = %d",
233*316acdacSPavithra Barithaya (unsigned)rc);
234*316acdacSPavithra Barithaya closePLDM();
235*316acdacSPavithra Barithaya return rc;
236*316acdacSPavithra Barithaya }
237*316acdacSPavithra Barithaya return pollfd.fd;
238*316acdacSPavithra Barithaya }
239*316acdacSPavithra Barithaya
closePLDM()2409b1a0b6bSPavithra Barithaya void PLDMInstanceManager::closePLDM()
2419b1a0b6bSPavithra Barithaya {
242*316acdacSPavithra Barithaya #if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
243*316acdacSPavithra Barithaya pldm_transport_mctp_demux_destroy(impl.mctpDemux);
244*316acdacSPavithra Barithaya impl.mctpDemux = nullptr;
245*316acdacSPavithra Barithaya #elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
246*316acdacSPavithra Barithaya pldm_transport_af_mctp_destroy(impl.afMctp);
247*316acdacSPavithra Barithaya impl.afMctp = nullptr;
248*316acdacSPavithra Barithaya #endif
2499b1a0b6bSPavithra Barithaya pldmTransport = NULL;
2509b1a0b6bSPavithra Barithaya }
2519b1a0b6bSPavithra Barithaya
252bb90afc7SBen Tyner /** @brief Send PLDM request
253bb90afc7SBen Tyner *
254bb90afc7SBen Tyner * @param[in] request - the request data
255bb90afc7SBen Tyner * @param[in] mcptEid - the mctp endpoint ID
256bb90afc7SBen Tyner *
257bb90afc7SBen Tyner * @pre a mctp instance must have been
258bb90afc7SBen Tyner * @return true if send is successful false otherwise
259bb90afc7SBen Tyner */
sendPldm(const std::vector<uint8_t> & request,uint8_t mctpEid)2609b1a0b6bSPavithra Barithaya bool PLDMInstanceManager::sendPldm(const std::vector<uint8_t>& request,
2619b1a0b6bSPavithra Barithaya uint8_t mctpEid)
262bb90afc7SBen Tyner {
2639b1a0b6bSPavithra Barithaya auto rc = openPLDM(mctpEid);
2649b1a0b6bSPavithra Barithaya if (rc)
265bb90afc7SBen Tyner {
266bb90afc7SBen Tyner trace::err("failed to connect to pldm");
267bb90afc7SBen Tyner return false;
268bb90afc7SBen Tyner }
269bb90afc7SBen Tyner
2709b1a0b6bSPavithra Barithaya pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
271bb90afc7SBen Tyner // send PLDM request
2729b1a0b6bSPavithra Barithaya auto pldmRc = pldm_transport_send_msg(pldmTransport, pldmTID,
2739b1a0b6bSPavithra Barithaya request.data(), request.size());
274bb90afc7SBen Tyner
275bb90afc7SBen Tyner trace::inf("sent pldm request");
276bb90afc7SBen Tyner
277bb90afc7SBen Tyner return pldmRc == PLDM_REQUESTER_SUCCESS ? true : false;
278bb90afc7SBen Tyner }
279bb90afc7SBen Tyner
280bb90afc7SBen Tyner /** @brief Prepare a request for SetStateEffecterStates
281bb90afc7SBen Tyner *
282bb90afc7SBen Tyner * @param[in] effecterId - the effecter ID
283bb90afc7SBen Tyner * @param[in] effecterCount - composite effecter count
284bb90afc7SBen Tyner * @param[in] stateIdPos - position of the state set
285bb90afc7SBen Tyner * @param[in] stateSetValue - the value to set the state
286bb90afc7SBen Tyner * @param[in] mcptEid - the MCTP endpoint ID
287bb90afc7SBen Tyner *
288bb90afc7SBen Tyner * @return PLDM request message to be sent to host, empty message on error
289bb90afc7SBen Tyner */
prepareSetEffecterReq(uint16_t effecterId,uint8_t effecterCount,uint8_t stateIdPos,uint8_t stateSetValue,uint8_t mctpEid)290a0c724d3SPatrick Williams std::vector<uint8_t> prepareSetEffecterReq(
291a0c724d3SPatrick Williams uint16_t effecterId, uint8_t effecterCount, uint8_t stateIdPos,
292a0c724d3SPatrick Williams uint8_t stateSetValue, uint8_t mctpEid)
293bb90afc7SBen Tyner {
29436b043e9SPavithra Barithaya PLDMInstanceManager& manager = PLDMInstanceManager::getInstance();
29536b043e9SPavithra Barithaya
29608f25b21SPavithra Barithaya // get pldm instance associated with the endpoint ID
29708f25b21SPavithra Barithaya uint8_t pldmInstanceID;
29836b043e9SPavithra Barithaya if (!manager.getPldmInstanceID(pldmInstanceID, mctpEid))
299bb90afc7SBen Tyner {
300bb90afc7SBen Tyner return std::vector<uint8_t>();
301bb90afc7SBen Tyner }
302bb90afc7SBen Tyner
303bb90afc7SBen Tyner // form the request message
304bb90afc7SBen Tyner std::vector<uint8_t> request(
305bb90afc7SBen Tyner sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
306bb90afc7SBen Tyner (effecterCount * sizeof(set_effecter_state_field)));
307bb90afc7SBen Tyner
308bb90afc7SBen Tyner // encode the state data with the change we want to elicit
309bb90afc7SBen Tyner std::vector<set_effecter_state_field> stateField;
310bb90afc7SBen Tyner for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
311bb90afc7SBen Tyner {
312bb90afc7SBen Tyner if (effecterPos == stateIdPos)
313bb90afc7SBen Tyner {
314bb90afc7SBen Tyner stateField.emplace_back(
315bb90afc7SBen Tyner set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
316bb90afc7SBen Tyner }
317bb90afc7SBen Tyner else
318bb90afc7SBen Tyner {
319bb90afc7SBen Tyner stateField.emplace_back(
320bb90afc7SBen Tyner set_effecter_state_field{PLDM_NO_CHANGE, 0});
321bb90afc7SBen Tyner }
322bb90afc7SBen Tyner }
323bb90afc7SBen Tyner
324bb90afc7SBen Tyner // encode the message with state data
325bb90afc7SBen Tyner auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
326bb90afc7SBen Tyner auto rc = encode_set_state_effecter_states_req(
32708f25b21SPavithra Barithaya pldmInstanceID, effecterId, effecterCount, stateField.data(),
32808f25b21SPavithra Barithaya requestMsg);
329bb90afc7SBen Tyner
330bb90afc7SBen Tyner if (rc != PLDM_SUCCESS)
331bb90afc7SBen Tyner {
332bb90afc7SBen Tyner trace::err("encode set effecter states request failed");
33336b043e9SPavithra Barithaya manager.freePLDMInstanceID(pldmInstanceID, mctpEid);
334bb90afc7SBen Tyner request.clear();
335bb90afc7SBen Tyner }
336bb90afc7SBen Tyner
337bb90afc7SBen Tyner return request;
338bb90afc7SBen Tyner }
339bb90afc7SBen Tyner
340bb90afc7SBen Tyner /** @brief Return map of sensor ID to SBE instance
341bb90afc7SBen Tyner *
342bb90afc7SBen Tyner * @param[in] stateSetId - the state set ID of interest
343bb90afc7SBen Tyner * @param[out] sensorInstanceMap - map of sensor to SBE instance
344bb90afc7SBen Tyner * @param[out] sensorOffset - position of sensor with state set ID within map
345bb90afc7SBen Tyner *
346bb90afc7SBen Tyner * @return true if sensor info is available false otherwise
347bb90afc7SBen Tyner */
fetchSensorInfo(uint16_t stateSetId,std::map<uint16_t,unsigned int> & sensorInstanceMap,uint8_t & sensorOffset)348bb90afc7SBen Tyner bool fetchSensorInfo(uint16_t stateSetId,
349bb90afc7SBen Tyner std::map<uint16_t, unsigned int>& sensorInstanceMap,
350bb90afc7SBen Tyner uint8_t& sensorOffset)
351bb90afc7SBen Tyner {
352bb90afc7SBen Tyner // get state sensor PDRs
353bb90afc7SBen Tyner std::vector<std::vector<uint8_t>> pdrs{};
354bb90afc7SBen Tyner if (!util::dbus::getStateSensorPdrs(pdrs, stateSetId))
355bb90afc7SBen Tyner {
356bb90afc7SBen Tyner return false;
357bb90afc7SBen Tyner }
358bb90afc7SBen Tyner
359bb90afc7SBen Tyner // check for any PDRs available
360bb90afc7SBen Tyner if (!pdrs.size())
361bb90afc7SBen Tyner {
362bb90afc7SBen Tyner trace::err("state sensor PDRs not present");
363bb90afc7SBen Tyner return false;
364bb90afc7SBen Tyner }
365bb90afc7SBen Tyner
366bb90afc7SBen Tyner // find the offset of specified sensor withing PDRs
367bb90afc7SBen Tyner bool offsetFound = false;
368bb90afc7SBen Tyner auto stateSensorPDR =
369bb90afc7SBen Tyner reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
370bb90afc7SBen Tyner auto possibleStatesPtr = stateSensorPDR->possible_states;
371bb90afc7SBen Tyner
372bb90afc7SBen Tyner for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
373bb90afc7SBen Tyner offset++)
374bb90afc7SBen Tyner {
375bb90afc7SBen Tyner auto possibleStates =
376bb90afc7SBen Tyner reinterpret_cast<const state_sensor_possible_states*>(
377bb90afc7SBen Tyner possibleStatesPtr);
378bb90afc7SBen Tyner
379bb90afc7SBen Tyner if (possibleStates->state_set_id == stateSetId)
380bb90afc7SBen Tyner {
381bb90afc7SBen Tyner sensorOffset = offset;
382bb90afc7SBen Tyner offsetFound = true;
383bb90afc7SBen Tyner break;
384bb90afc7SBen Tyner }
385bb90afc7SBen Tyner possibleStatesPtr += sizeof(possibleStates->state_set_id) +
386bb90afc7SBen Tyner sizeof(possibleStates->possible_states_size) +
387bb90afc7SBen Tyner possibleStates->possible_states_size;
388bb90afc7SBen Tyner }
389bb90afc7SBen Tyner
390bb90afc7SBen Tyner if (!offsetFound)
391bb90afc7SBen Tyner {
392bb90afc7SBen Tyner trace::err("state sensor not found");
393bb90afc7SBen Tyner return false;
394bb90afc7SBen Tyner }
395bb90afc7SBen Tyner
396bb90afc7SBen Tyner // map sensor ID to equivelent 16 bit value
397bb90afc7SBen Tyner std::map<uint32_t, uint16_t> entityInstMap{};
398bb90afc7SBen Tyner for (auto& pdr : pdrs)
399bb90afc7SBen Tyner {
400bb90afc7SBen Tyner auto pdrPtr =
401bb90afc7SBen Tyner reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
402bb90afc7SBen Tyner uint32_t key = pdrPtr->sensor_id;
403bb90afc7SBen Tyner entityInstMap.emplace(key, static_cast<uint16_t>(pdrPtr->sensor_id));
404bb90afc7SBen Tyner }
405bb90afc7SBen Tyner
406bb90afc7SBen Tyner // map sensor ID to zero based SBE instance
407bb90afc7SBen Tyner unsigned int position = 0;
40827dd6368SPatrick Williams for (const auto& pair : entityInstMap)
409bb90afc7SBen Tyner {
410bb90afc7SBen Tyner sensorInstanceMap.emplace(pair.second, position);
411bb90afc7SBen Tyner position++;
412bb90afc7SBen Tyner }
413bb90afc7SBen Tyner
414bb90afc7SBen Tyner return true;
415bb90afc7SBen Tyner }
416bb90afc7SBen Tyner
417bb90afc7SBen Tyner /** @brief Return map of SBE instance to effecter ID
418bb90afc7SBen Tyner *
419bb90afc7SBen Tyner * @param[in] stateSetId - the state set ID of interest
420bb90afc7SBen Tyner * @param[out] instanceToEffecterMap - map of sbe instance to effecter ID
421bb90afc7SBen Tyner * @param[out] effecterCount - composite effecter count
422bb90afc7SBen Tyner * @param[out] stateIdPos - position of effecter with state set ID within map
423bb90afc7SBen Tyner *
424bb90afc7SBen Tyner * @return true if effector info is available false otherwise
425bb90afc7SBen Tyner */
fetchEffecterInfo(uint16_t stateSetId,std::map<unsigned int,uint16_t> & instanceToEffecterMap,uint8_t & effecterCount,uint8_t & stateIdPos)426bb90afc7SBen Tyner bool fetchEffecterInfo(uint16_t stateSetId,
427bb90afc7SBen Tyner std::map<unsigned int, uint16_t>& instanceToEffecterMap,
428bb90afc7SBen Tyner uint8_t& effecterCount, uint8_t& stateIdPos)
429bb90afc7SBen Tyner {
430bb90afc7SBen Tyner // get state effecter PDRs
431bb90afc7SBen Tyner std::vector<std::vector<uint8_t>> pdrs{};
432bb90afc7SBen Tyner if (!util::dbus::getStateEffecterPdrs(pdrs, stateSetId))
433bb90afc7SBen Tyner {
434bb90afc7SBen Tyner return false;
435bb90afc7SBen Tyner }
436bb90afc7SBen Tyner
437bb90afc7SBen Tyner // check for any PDRs available
438bb90afc7SBen Tyner if (!pdrs.size())
439bb90afc7SBen Tyner {
440bb90afc7SBen Tyner trace::err("state effecter PDRs not present");
441bb90afc7SBen Tyner return false;
442bb90afc7SBen Tyner }
443bb90afc7SBen Tyner
444bb90afc7SBen Tyner // find the offset of specified effector within PDRs
445bb90afc7SBen Tyner bool offsetFound = false;
446bb90afc7SBen Tyner auto stateEffecterPDR =
447bb90afc7SBen Tyner reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
448bb90afc7SBen Tyner auto possibleStatesPtr = stateEffecterPDR->possible_states;
449bb90afc7SBen Tyner
450bb90afc7SBen Tyner for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
451bb90afc7SBen Tyner offset++)
452bb90afc7SBen Tyner {
453bb90afc7SBen Tyner auto possibleStates =
454bb90afc7SBen Tyner reinterpret_cast<const state_effecter_possible_states*>(
455bb90afc7SBen Tyner possibleStatesPtr);
456bb90afc7SBen Tyner
457bb90afc7SBen Tyner if (possibleStates->state_set_id == stateSetId)
458bb90afc7SBen Tyner {
459bb90afc7SBen Tyner stateIdPos = offset;
460bb90afc7SBen Tyner effecterCount = stateEffecterPDR->composite_effecter_count;
461bb90afc7SBen Tyner offsetFound = true;
462bb90afc7SBen Tyner break;
463bb90afc7SBen Tyner }
464bb90afc7SBen Tyner possibleStatesPtr += sizeof(possibleStates->state_set_id) +
465bb90afc7SBen Tyner sizeof(possibleStates->possible_states_size) +
466bb90afc7SBen Tyner possibleStates->possible_states_size;
467bb90afc7SBen Tyner }
468bb90afc7SBen Tyner
469bb90afc7SBen Tyner if (!offsetFound)
470bb90afc7SBen Tyner {
471bb90afc7SBen Tyner trace::err("state set effecter not found");
472bb90afc7SBen Tyner return false;
473bb90afc7SBen Tyner }
474bb90afc7SBen Tyner
475bb90afc7SBen Tyner // map effecter ID to equivelent 16 bit value
476bb90afc7SBen Tyner std::map<uint32_t, uint16_t> entityInstMap{};
477bb90afc7SBen Tyner for (auto& pdr : pdrs)
478bb90afc7SBen Tyner {
479bb90afc7SBen Tyner auto pdrPtr =
480bb90afc7SBen Tyner reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
481bb90afc7SBen Tyner uint32_t key = pdrPtr->effecter_id;
482bb90afc7SBen Tyner entityInstMap.emplace(key, static_cast<uint16_t>(pdrPtr->effecter_id));
483bb90afc7SBen Tyner }
484bb90afc7SBen Tyner
485bb90afc7SBen Tyner // map zero based SBE instance to effecter ID
486bb90afc7SBen Tyner unsigned int position = 0;
48727dd6368SPatrick Williams for (const auto& pair : entityInstMap)
488bb90afc7SBen Tyner {
489bb90afc7SBen Tyner instanceToEffecterMap.emplace(position, pair.second);
490bb90afc7SBen Tyner position++;
491bb90afc7SBen Tyner }
492bb90afc7SBen Tyner
493bb90afc7SBen Tyner return true;
494bb90afc7SBen Tyner }
495bb90afc7SBen Tyner
496bb90afc7SBen Tyner /** @brief Reset SBE using HBRT PLDM interface */
hresetSbe(unsigned int sbeInstance)497bb90afc7SBen Tyner bool hresetSbe(unsigned int sbeInstance)
498bb90afc7SBen Tyner {
499bb90afc7SBen Tyner trace::inf("requesting sbe hreset");
500bb90afc7SBen Tyner
501bb90afc7SBen Tyner // get effecter info
502bb90afc7SBen Tyner std::map<unsigned int, uint16_t> sbeInstanceToEffecter;
503bb90afc7SBen Tyner uint8_t SBEEffecterCount = 0;
504bb90afc7SBen Tyner uint8_t sbeMaintenanceStatePosition = 0;
505bb90afc7SBen Tyner
506bb90afc7SBen Tyner if (!fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
507bb90afc7SBen Tyner sbeInstanceToEffecter, SBEEffecterCount,
508bb90afc7SBen Tyner sbeMaintenanceStatePosition))
509bb90afc7SBen Tyner {
510bb90afc7SBen Tyner return false;
511bb90afc7SBen Tyner }
512bb90afc7SBen Tyner
513bb90afc7SBen Tyner // find the state effecter ID for the given SBE instance
514bb90afc7SBen Tyner auto effecterEntry = sbeInstanceToEffecter.find(sbeInstance);
515bb90afc7SBen Tyner if (effecterEntry == sbeInstanceToEffecter.end())
516bb90afc7SBen Tyner {
517bb90afc7SBen Tyner trace::err("failed to find effecter for SBE");
518bb90afc7SBen Tyner return false;
519bb90afc7SBen Tyner }
520bb90afc7SBen Tyner
521bb90afc7SBen Tyner // create request to HRESET the SBE
522bb90afc7SBen Tyner constexpr uint8_t hbrtMctpEid = 10; // HBRT MCTP EID
523bb90afc7SBen Tyner
524bb90afc7SBen Tyner auto request = prepareSetEffecterReq(
525bb90afc7SBen Tyner effecterEntry->second, SBEEffecterCount, sbeMaintenanceStatePosition,
526bb90afc7SBen Tyner SBE_RETRY_REQUIRED, hbrtMctpEid);
527bb90afc7SBen Tyner
528bb90afc7SBen Tyner if (request.empty())
529bb90afc7SBen Tyner {
530bb90afc7SBen Tyner trace::err("HRESET effecter request empty");
531bb90afc7SBen Tyner return false;
532bb90afc7SBen Tyner }
533bb90afc7SBen Tyner
534bb90afc7SBen Tyner // get sensor info for validating sensor change
535bb90afc7SBen Tyner std::map<uint16_t, unsigned int> sensorToSbeInstance;
536bb90afc7SBen Tyner uint8_t sbeSensorOffset = 0;
537bb90afc7SBen Tyner if (!fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSbeInstance,
538bb90afc7SBen Tyner sbeSensorOffset))
539bb90afc7SBen Tyner {
54036b043e9SPavithra Barithaya PLDMInstanceManager& manager = PLDMInstanceManager::getInstance();
54136b043e9SPavithra Barithaya auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&request);
54236b043e9SPavithra Barithaya manager.freePLDMInstanceID(reqhdr->instance_id, hbrtMctpEid);
543bb90afc7SBen Tyner return false;
544bb90afc7SBen Tyner }
545bb90afc7SBen Tyner
546bb90afc7SBen Tyner // register signal change listener
547bb90afc7SBen Tyner std::string hresetStatus = "requested";
548bb90afc7SBen Tyner constexpr auto interface = "xyz.openbmc_project.PLDM.Event";
549bb90afc7SBen Tyner constexpr auto path = "/xyz/openbmc_project/pldm";
550bb90afc7SBen Tyner constexpr auto member = "StateSensorEvent";
551bb90afc7SBen Tyner
552bb90afc7SBen Tyner auto bus = sdbusplus::bus::new_default();
553bb90afc7SBen Tyner std::unique_ptr<sdbusplus::bus::match_t> match =
554bb90afc7SBen Tyner std::make_unique<sdbusplus::bus::match_t>(
555bb90afc7SBen Tyner bus,
556bb90afc7SBen Tyner sdbusplus::bus::match::rules::type::signal() +
557bb90afc7SBen Tyner sdbusplus::bus::match::rules::member(member) +
558bb90afc7SBen Tyner sdbusplus::bus::match::rules::path(path) +
559bb90afc7SBen Tyner sdbusplus::bus::match::rules::interface(interface),
560bb90afc7SBen Tyner [&](auto& msg) {
561bb90afc7SBen Tyner uint8_t sensorTid{};
562bb90afc7SBen Tyner uint16_t sensorId{};
563bb90afc7SBen Tyner uint8_t msgSensorOffset{};
564bb90afc7SBen Tyner uint8_t eventState{};
565bb90afc7SBen Tyner uint8_t previousEventState{};
566bb90afc7SBen Tyner
567bb90afc7SBen Tyner // get sensor event details
568bb90afc7SBen Tyner msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
569bb90afc7SBen Tyner previousEventState);
570bb90afc7SBen Tyner
571bb90afc7SBen Tyner // does sensor offset match?
572bb90afc7SBen Tyner if (sbeSensorOffset == msgSensorOffset)
573bb90afc7SBen Tyner {
574bb90afc7SBen Tyner // does sensor ID match?
575bb90afc7SBen Tyner auto sensorEntry = sensorToSbeInstance.find(sensorId);
576bb90afc7SBen Tyner if (sensorEntry != sensorToSbeInstance.end())
577bb90afc7SBen Tyner {
578bb90afc7SBen Tyner const uint8_t instance = sensorEntry->second;
579bb90afc7SBen Tyner
580bb90afc7SBen Tyner // if instances matche check status
581bb90afc7SBen Tyner if (instance == sbeInstance)
582bb90afc7SBen Tyner {
583a0c724d3SPatrick Williams if (eventState ==
584a0c724d3SPatrick Williams static_cast<uint8_t>(SBE_HRESET_READY))
585bb90afc7SBen Tyner {
586bb90afc7SBen Tyner hresetStatus = "success";
587bb90afc7SBen Tyner }
588bb90afc7SBen Tyner else if (eventState ==
589bb90afc7SBen Tyner static_cast<uint8_t>(SBE_HRESET_FAILED))
590bb90afc7SBen Tyner {
591bb90afc7SBen Tyner hresetStatus = "fail";
592bb90afc7SBen Tyner }
593bb90afc7SBen Tyner }
594bb90afc7SBen Tyner }
595bb90afc7SBen Tyner }
596bb90afc7SBen Tyner });
597bb90afc7SBen Tyner
598bb90afc7SBen Tyner // send request to issue hreset of sbe
5999b1a0b6bSPavithra Barithaya PLDMInstanceManager& manager = PLDMInstanceManager::getInstance();
6009b1a0b6bSPavithra Barithaya if (!(manager.sendPldm(request, hbrtMctpEid)))
601bb90afc7SBen Tyner {
602bb90afc7SBen Tyner trace::err("send pldm request failed");
60336b043e9SPavithra Barithaya auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&request);
60436b043e9SPavithra Barithaya manager.freePLDMInstanceID(reqhdr->instance_id, hbrtMctpEid);
60536b043e9SPavithra Barithaya
606bb90afc7SBen Tyner return false;
607bb90afc7SBen Tyner }
608bb90afc7SBen Tyner
609bb90afc7SBen Tyner // keep track of elapsed time
610bb90afc7SBen Tyner uint64_t timeRemaining = 60000000; // microseconds, 1 minute
611bb90afc7SBen Tyner std::chrono::steady_clock::time_point begin =
612bb90afc7SBen Tyner std::chrono::steady_clock::now();
613bb90afc7SBen Tyner
614bb90afc7SBen Tyner // wait for status update or timeout
615bb90afc7SBen Tyner trace::inf("waiting on sbe hreset");
616bb90afc7SBen Tyner while ("requested" == hresetStatus && 0 != timeRemaining)
617bb90afc7SBen Tyner {
618bb90afc7SBen Tyner bus.wait(timeRemaining);
619bb90afc7SBen Tyner uint64_t timeElapsed =
620bb90afc7SBen Tyner std::chrono::duration_cast<std::chrono::microseconds>(
621bb90afc7SBen Tyner std::chrono::steady_clock::now() - begin)
622bb90afc7SBen Tyner .count();
623bb90afc7SBen Tyner
624bb90afc7SBen Tyner timeRemaining =
625bb90afc7SBen Tyner timeElapsed > timeRemaining ? 0 : timeRemaining - timeElapsed;
626bb90afc7SBen Tyner
627bb90afc7SBen Tyner bus.process_discard();
628bb90afc7SBen Tyner }
629bb90afc7SBen Tyner
630bb90afc7SBen Tyner if (0 == timeRemaining)
631bb90afc7SBen Tyner {
632bb90afc7SBen Tyner trace::err("hreset timed out");
633bb90afc7SBen Tyner }
634bb90afc7SBen Tyner
63536b043e9SPavithra Barithaya auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&request);
63636b043e9SPavithra Barithaya manager.freePLDMInstanceID(reqhdr->instance_id, hbrtMctpEid);
6379b1a0b6bSPavithra Barithaya manager.closePLDM();
638bb90afc7SBen Tyner
639bb90afc7SBen Tyner return hresetStatus == "success" ? true : false;
640bb90afc7SBen Tyner }
641bb90afc7SBen Tyner
642bb90afc7SBen Tyner } // namespace pldm
643bb90afc7SBen Tyner } // namespace util
644