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 
54     explicit TerminusManager(sdeventplus::Event& /* event */,
55                              RequesterHandler& handler,
56                              pldm::InstanceIdDb& instanceIdDb,
57                              TerminiMapper& termini, Manager* manager) :
58         handler(handler),
59         instanceIdDb(instanceIdDb), termini(termini),
60         tidPool(tidPoolSize, false), manager(manager)
61     {
62         // DSP0240 v1.1.0 table-8, special value: 0,0xFF = reserved
63         tidPool[0] = true;
64         tidPool[PLDM_TID_RESERVED] = true;
65     }
66 
67     /** @brief start a coroutine to discover terminus
68      *
69      *  @param[in] mctpInfos - list information of the MCTP endpoints
70      */
71     void discoverMctpTerminus(const MctpInfos& mctpInfos);
72 
73     /** @brief remove MCTP endpoints
74      *
75      *  @param[in] mctpInfos - list information of the MCTP endpoints
76      */
77     void removeMctpTerminus(const MctpInfos& mctpInfos);
78 
79     /** @brief Send request PLDM message to tid. The function will return when
80      *         received the response message from terminus. The function will
81      *         auto get the instanceID from libmctp and update to request
82      *         message.
83      *
84      *  @param[in] tid - Destination TID
85      *  @param[in] request - request PLDM message
86      *  @param[out] responseMsg - response PLDM message
87      *  @param[out] responseLen - length of response PLDM message
88      *  @return coroutine return_value - PLDM completion code
89      */
90     exec::task<int> sendRecvPldmMsg(pldm_tid_t tid, Request& request,
91                                     const pldm_msg** responseMsg,
92                                     size_t* responseLen);
93 
94     /** @brief Send request PLDM message to eid. The function will
95      *         return when received the response message from terminus.
96      *
97      *  @param[in] eid - Destination EID
98      *  @param[in] request - request PLDM message
99      *  @param[out] responseMsg - response PLDM message
100      *  @param[out] responseLen - length of response PLDM message
101      *  @return coroutine return_value - PLDM completion code
102      */
103     virtual exec::task<int>
104         sendRecvPldmMsgOverMctp(mctp_eid_t eid, Request& request,
105                                 const pldm_msg** responseMsg,
106                                 size_t* responseLen);
107 
108     /** @brief member functions to map/unmap tid
109      */
110     std::optional<MctpInfo> toMctpInfo(const pldm_tid_t& tid);
111 
112     /** @brief Member functions to response the TID of specific MCTP interface
113      *
114      *  @param[in] mctpInfos - list information of the MCTP endpoints
115      *
116      *  @return tid - Terminus tid
117      */
118     std::optional<pldm_tid_t> toTid(const MctpInfo& mctpInfo) const;
119 
120     /** @brief Member functions to find the TID for MCTP interface. Response the
121      *         Terminus TID when mctpInfo is already in the data base. Response
122      *         new tid from pool when mctpInfo is new.
123      *
124      *  @param[in] mctpInfos - list information of the MCTP endpoints
125      *
126      *  @return tid - Terminus tid
127      */
128     std::optional<pldm_tid_t> mapTid(const MctpInfo& mctpInfo);
129 
130     /** @brief Member functions to store the mctp info and tid to terminus info
131      *         list.
132      *
133      *  @param[in] mctpInfos - list information of the MCTP endpoints
134      *  @param[in] tid - Destination TID
135      *
136      *  @return tid - Terminus tid
137      */
138     std::optional<pldm_tid_t> storeTerminusInfo(const MctpInfo& mctpInfo,
139                                                 pldm_tid_t tid);
140 
141     /** @brief Member functions to remove the TID from the transportLayer and
142      *         mctpInfo table
143      *
144      *  @param[in] tid - Destination TID
145      *
146      *  @return true/false - True when tid in the table otherwise return false
147      */
148     bool unmapTid(const pldm_tid_t& tid);
149 
150   private:
151     /** @brief Find the terminus object pointer in termini list.
152      *
153      *  @param[in] mctpInfos - list information of the MCTP endpoints
154      */
155     TerminiMapper::iterator findTerminusPtr(const MctpInfo& mctpInfo);
156 
157     /** @brief The coroutine task execute by discoverMctpTerminus()
158      *
159      *  @return coroutine return_value - PLDM completion code
160      */
161     exec::task<int> discoverMctpTerminusTask();
162 
163     /** @brief Initialize terminus and then instantiate terminus object to keeps
164      *         the data fetched from terminus
165      *
166      *  @param[in] mctpInfo - information of the MCTP endpoints
167      *  @return coroutine return_value - PLDM completion code
168      */
169     exec::task<int> initMctpTerminus(const MctpInfo& mctpInfo);
170 
171     /** @brief Send getTID PLDM command to destination EID and then return the
172      *         value of tid in reference parameter.
173      *
174      *  @param[in] eid - Destination EID
175      *  @param[out] tid - Terminus TID
176      *  @return coroutine return_value - PLDM completion code
177      */
178     exec::task<int> getTidOverMctp(mctp_eid_t eid, pldm_tid_t* tid);
179 
180     /** @brief Send setTID command to destination EID.
181      *
182      *  @param[in] eid - Destination EID
183      *  @param[in] tid - Destination TID
184      *  @return coroutine return_value - PLDM completion code
185      */
186     exec::task<int> setTidOverMctp(mctp_eid_t eid, pldm_tid_t tid);
187 
188     /** @brief Send getPLDMTypes command to destination TID and then return the
189      *         value of supportedTypes in reference parameter.
190      *
191      *  @param[in] tid - Destination TID
192      *  @param[out] supportedTypes - Supported Types returned from terminus
193      *  @return coroutine return_value - PLDM completion code
194      */
195     exec::task<int> getPLDMTypes(pldm_tid_t tid, uint64_t& supportedTypes);
196 
197     /** @brief Send getPLDMCommands command to destination TID and then return
198      *         the value of supportedCommands in reference parameter.
199      *
200      *  @param[in] tid - Destination TID
201      *  @param[in] type - PLDM Type
202      *  @param[in] supportedCmds - Supported commands returned from terminus
203      *                             for specific type
204      *  @return coroutine return_value - PLDM completion code
205      */
206     exec::task<int> getPLDMCommands(pldm_tid_t tid, uint8_t type,
207                                     bitfield8_t* supportedCmds);
208 
209     /** @brief Reference to a Handler object that manages the request/response
210      *         logic.
211      */
212     RequesterHandler& handler;
213 
214     /** @brief Reference to the instanceID data base from libpldm */
215     pldm::InstanceIdDb& instanceIdDb;
216 
217     /** @brief Managed termini list */
218     TerminiMapper& termini;
219 
220     /** @brief tables for maintaining assigned TID */
221     std::vector<bool> tidPool;
222 
223     /** @brief Store the supported transport layers of specific TID */
224     std::map<pldm_tid_t, SupportedTransportLayer> transportLayerTable;
225 
226     /** @brief Store the supported MCTP interface info of specific TID */
227     std::map<pldm_tid_t, MctpInfo> mctpInfoTable;
228 
229     /** @brief A queue of MctpInfos to be discovered **/
230     std::queue<MctpInfos> queuedMctpInfos{};
231 
232     /** @brief coroutine handle of discoverTerminusTask */
233     std::optional<std::pair<exec::async_scope, std::optional<int>>>
234         discoverMctpTerminusTaskHandle{};
235 
236     /** @brief A Manager interface for calling the hook functions **/
237     Manager* manager;
238 };
239 } // namespace platform_mc
240 } // namespace pldm
241