1 #pragma once
2 
3 #include "config.h"
4 
5 #include "libpldm/platform.h"
6 #include "libpldm/pldm.h"
7 
8 #include "requester/handler.hpp"
9 #include "requester/mctp_endpoint_discovery.hpp"
10 #include "terminus.hpp"
11 
12 #include <limits>
13 #include <map>
14 #include <memory>
15 #include <optional>
16 #include <queue>
17 #include <utility>
18 #include <vector>
19 
20 namespace pldm
21 {
22 
23 enum class SupportedTransportLayer
24 {
25     MCTP
26 };
27 
28 namespace platform_mc
29 {
30 
31 /** @brief Size of TID Pool in pldmd */
32 constexpr size_t tidPoolSize = std::numeric_limits<pldm_tid_t>::max() + 1;
33 /** @brief Type definition for Requester request handler */
34 using RequesterHandler = requester::Handler<requester::Request>;
35 /** @brief Type definition for Terminus handler mapper */
36 using TerminiMapper = std::map<pldm_tid_t, std::shared_ptr<Terminus>>;
37 
38 class Manager;
39 /**
40  * @brief TerminusManager
41  *
42  * TerminusManager class to discover and initialize PLDM terminus.
43  */
44 class TerminusManager
45 {
46   public:
47     TerminusManager() = delete;
48     TerminusManager(const TerminusManager&) = delete;
49     TerminusManager(TerminusManager&&) = delete;
50     TerminusManager& operator=(const TerminusManager&) = delete;
51     TerminusManager& operator=(TerminusManager&&) = delete;
52     virtual ~TerminusManager() = default;
53 
TerminusManager(sdeventplus::Event &,RequesterHandler & handler,pldm::InstanceIdDb & instanceIdDb,TerminiMapper & termini,Manager * manager,mctp_eid_t localEid)54     explicit TerminusManager(
55         sdeventplus::Event& /* event */, RequesterHandler& handler,
56         pldm::InstanceIdDb& instanceIdDb, TerminiMapper& termini,
57         Manager* manager, mctp_eid_t localEid) :
58         handler(handler), instanceIdDb(instanceIdDb), termini(termini),
59         tidPool(tidPoolSize, false), manager(manager), localEid(localEid)
60     {
61         // DSP0240 v1.1.0 table-8, special value: 0,0xFF = reserved
62         tidPool[0] = true;
63         tidPool[PLDM_TID_RESERVED] = true;
64     }
65 
66     /** @brief start a coroutine to discover terminus
67      *
68      *  @param[in] mctpInfos - list information of the MCTP endpoints
69      */
70     void discoverMctpTerminus(const MctpInfos& mctpInfos);
71 
72     /** @brief remove MCTP endpoints
73      *
74      *  @param[in] mctpInfos - list information of the MCTP endpoints
75      */
76     void removeMctpTerminus(const MctpInfos& mctpInfos);
77 
78     /** @brief Send request PLDM message to tid. The function will return when
79      *         received the response message from terminus. The function will
80      *         auto get the instanceID from libmctp and update to request
81      *         message.
82      *
83      *  @param[in] tid - Destination TID
84      *  @param[in] request - request PLDM message
85      *  @param[out] responseMsg - response PLDM message
86      *  @param[out] responseLen - length of response PLDM message
87      *  @return coroutine return_value - PLDM completion code
88      */
89     exec::task<int> sendRecvPldmMsg(pldm_tid_t tid, Request& request,
90                                     const pldm_msg** responseMsg,
91                                     size_t* responseLen);
92 
93     /** @brief Send request PLDM message to eid. The function will
94      *         return when received the response message from terminus.
95      *
96      *  @param[in] eid - Destination EID
97      *  @param[in] request - request PLDM message
98      *  @param[out] responseMsg - response PLDM message
99      *  @param[out] responseLen - length of response PLDM message
100      *  @return coroutine return_value - PLDM completion code
101      */
102     virtual exec::task<int> sendRecvPldmMsgOverMctp(
103         mctp_eid_t eid, Request& request, const pldm_msg** responseMsg,
104         size_t* responseLen);
105 
106     /** @brief member functions to map/unmap tid
107      */
108     std::optional<MctpInfo> toMctpInfo(const pldm_tid_t& tid);
109 
110     /** @brief Member functions to response the TID of specific MCTP interface
111      *
112      *  @param[in] mctpInfos - list information of the MCTP endpoints
113      *
114      *  @return tid - Terminus tid
115      */
116     std::optional<pldm_tid_t> toTid(const MctpInfo& mctpInfo) const;
117 
118     /** @brief Member functions to find the TID for MCTP interface. Response the
119      *         Terminus TID when mctpInfo is already in the data base. Response
120      *         new tid from pool when mctpInfo is new.
121      *
122      *  @param[in] mctpInfos - list information of the MCTP endpoints
123      *
124      *  @return tid - Terminus tid
125      */
126     std::optional<pldm_tid_t> mapTid(const MctpInfo& mctpInfo);
127 
128     /** @brief Member functions to store the mctp info and tid to terminus info
129      *         list.
130      *
131      *  @param[in] mctpInfos - list information of the MCTP endpoints
132      *  @param[in] tid - Destination TID
133      *
134      *  @return tid - Terminus tid
135      */
136     std::optional<pldm_tid_t>
137         storeTerminusInfo(const MctpInfo& mctpInfo, pldm_tid_t tid);
138 
139     /** @brief Member functions to remove the TID from the transportLayer and
140      *         mctpInfo table
141      *
142      *  @param[in] tid - Destination TID
143      *
144      *  @return true/false - True when tid in the table otherwise return false
145      */
146     bool unmapTid(const pldm_tid_t& tid);
147 
148     /** @brief getter of local EID
149      *
150      *  @return uint8_t - local EID
151      */
getLocalEid()152     mctp_eid_t getLocalEid()
153     {
154         return localEid;
155     }
156 
157   private:
158     /** @brief Find the terminus object pointer in termini list.
159      *
160      *  @param[in] mctpInfos - list information of the MCTP endpoints
161      */
162     TerminiMapper::iterator findTerminusPtr(const MctpInfo& mctpInfo);
163 
164     /** @brief The coroutine task execute by discoverMctpTerminus()
165      *
166      *  @return coroutine return_value - PLDM completion code
167      */
168     exec::task<int> discoverMctpTerminusTask();
169 
170     /** @brief Initialize terminus and then instantiate terminus object to keeps
171      *         the data fetched from terminus
172      *
173      *  @param[in] mctpInfo - information of the MCTP endpoints
174      *  @return coroutine return_value - PLDM completion code
175      */
176     exec::task<int> initMctpTerminus(const MctpInfo& mctpInfo);
177 
178     /** @brief Send getTID PLDM command to destination EID and then return the
179      *         value of tid in reference parameter.
180      *
181      *  @param[in] eid - Destination EID
182      *  @param[out] tid - Terminus TID
183      *  @return coroutine return_value - PLDM completion code
184      */
185     exec::task<int> getTidOverMctp(mctp_eid_t eid, pldm_tid_t* tid);
186 
187     /** @brief Send setTID command to destination EID.
188      *
189      *  @param[in] eid - Destination EID
190      *  @param[in] tid - Destination TID
191      *  @return coroutine return_value - PLDM completion code
192      */
193     exec::task<int> setTidOverMctp(mctp_eid_t eid, pldm_tid_t tid);
194 
195     /** @brief Send getPLDMTypes command to destination TID and then return the
196      *         value of supportedTypes in reference parameter.
197      *
198      *  @param[in] tid - Destination TID
199      *  @param[out] supportedTypes - Supported Types returned from terminus
200      *  @return coroutine return_value - PLDM completion code
201      */
202     exec::task<int> getPLDMTypes(pldm_tid_t tid, uint64_t& supportedTypes);
203 
204     /** @brief Send getPLDMVersion command to destination TID and then return
205      *         the version of the PLDM supported type.
206      *
207      *  @param[in] tid - Destination TID
208      *  @param[in] type - PLDM Type
209      *  @param[out] version - PLDM Type version
210      *  @return coroutine return_value - PLDM completion code
211      */
212     exec::task<int> getPLDMVersion(pldm_tid_t tid, uint8_t type,
213                                    ver32_t* version);
214 
215     /** @brief Send getPLDMCommands command to destination TID and then return
216      *         the value of supportedCommands in reference parameter.
217      *
218      *  @param[in] tid - Destination TID
219      *  @param[in] type - PLDM Type
220      *  @param[in] version - PLDM Type version
221      *  @param[in] supportedCmds - Supported commands returned from terminus
222      *                             for specific type
223      *  @return coroutine return_value - PLDM completion code
224      */
225     exec::task<int> getPLDMCommands(pldm_tid_t tid, uint8_t type,
226                                     ver32_t version,
227                                     bitfield8_t* supportedCmds);
228 
229     /** @brief Reference to a Handler object that manages the request/response
230      *         logic.
231      */
232     RequesterHandler& handler;
233 
234     /** @brief Reference to the instanceID data base from libpldm */
235     pldm::InstanceIdDb& instanceIdDb;
236 
237     /** @brief Managed termini list */
238     TerminiMapper& termini;
239 
240     /** @brief tables for maintaining assigned TID */
241     std::vector<bool> tidPool;
242 
243     /** @brief Store the supported transport layers of specific TID */
244     std::map<pldm_tid_t, SupportedTransportLayer> transportLayerTable;
245 
246     /** @brief Store the supported MCTP interface info of specific TID */
247     std::map<pldm_tid_t, MctpInfo> mctpInfoTable;
248 
249     /** @brief A queue of MctpInfos to be discovered **/
250     std::queue<MctpInfos> queuedMctpInfos{};
251 
252     /** @brief coroutine handle of discoverTerminusTask */
253     std::optional<std::pair<exec::async_scope, std::optional<int>>>
254         discoverMctpTerminusTaskHandle{};
255 
256     /** @brief A Manager interface for calling the hook functions **/
257     Manager* manager;
258 
259     /** @brief local EID */
260     mctp_eid_t localEid;
261 };
262 } // namespace platform_mc
263 } // namespace pldm
264