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), instanceIdDb(instanceIdDb), termini(termini),
59         tidPool(tidPoolSize, false), manager(manager)
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   private:
149     /** @brief Find the terminus object pointer in termini list.
150      *
151      *  @param[in] mctpInfos - list information of the MCTP endpoints
152      */
153     TerminiMapper::iterator findTerminusPtr(const MctpInfo& mctpInfo);
154 
155     /** @brief The coroutine task execute by discoverMctpTerminus()
156      *
157      *  @return coroutine return_value - PLDM completion code
158      */
159     exec::task<int> discoverMctpTerminusTask();
160 
161     /** @brief Initialize terminus and then instantiate terminus object to keeps
162      *         the data fetched from terminus
163      *
164      *  @param[in] mctpInfo - information of the MCTP endpoints
165      *  @return coroutine return_value - PLDM completion code
166      */
167     exec::task<int> initMctpTerminus(const MctpInfo& mctpInfo);
168 
169     /** @brief Send getTID PLDM command to destination EID and then return the
170      *         value of tid in reference parameter.
171      *
172      *  @param[in] eid - Destination EID
173      *  @param[out] tid - Terminus TID
174      *  @return coroutine return_value - PLDM completion code
175      */
176     exec::task<int> getTidOverMctp(mctp_eid_t eid, pldm_tid_t* tid);
177 
178     /** @brief Send setTID command to destination EID.
179      *
180      *  @param[in] eid - Destination EID
181      *  @param[in] tid - Destination TID
182      *  @return coroutine return_value - PLDM completion code
183      */
184     exec::task<int> setTidOverMctp(mctp_eid_t eid, pldm_tid_t tid);
185 
186     /** @brief Send getPLDMTypes command to destination TID and then return the
187      *         value of supportedTypes in reference parameter.
188      *
189      *  @param[in] tid - Destination TID
190      *  @param[out] supportedTypes - Supported Types returned from terminus
191      *  @return coroutine return_value - PLDM completion code
192      */
193     exec::task<int> getPLDMTypes(pldm_tid_t tid, uint64_t& supportedTypes);
194 
195     /** @brief Send getPLDMCommands command to destination TID and then return
196      *         the value of supportedCommands in reference parameter.
197      *
198      *  @param[in] tid - Destination TID
199      *  @param[in] type - PLDM Type
200      *  @param[in] supportedCmds - Supported commands returned from terminus
201      *                             for specific type
202      *  @return coroutine return_value - PLDM completion code
203      */
204     exec::task<int> getPLDMCommands(pldm_tid_t tid, uint8_t type,
205                                     bitfield8_t* supportedCmds);
206 
207     /** @brief Reference to a Handler object that manages the request/response
208      *         logic.
209      */
210     RequesterHandler& handler;
211 
212     /** @brief Reference to the instanceID data base from libpldm */
213     pldm::InstanceIdDb& instanceIdDb;
214 
215     /** @brief Managed termini list */
216     TerminiMapper& termini;
217 
218     /** @brief tables for maintaining assigned TID */
219     std::vector<bool> tidPool;
220 
221     /** @brief Store the supported transport layers of specific TID */
222     std::map<pldm_tid_t, SupportedTransportLayer> transportLayerTable;
223 
224     /** @brief Store the supported MCTP interface info of specific TID */
225     std::map<pldm_tid_t, MctpInfo> mctpInfoTable;
226 
227     /** @brief A queue of MctpInfos to be discovered **/
228     std::queue<MctpInfos> queuedMctpInfos{};
229 
230     /** @brief coroutine handle of discoverTerminusTask */
231     std::optional<std::pair<exec::async_scope, std::optional<int>>>
232         discoverMctpTerminusTaskHandle{};
233 
234     /** @brief A Manager interface for calling the hook functions **/
235     Manager* manager;
236 };
237 } // namespace platform_mc
238 } // namespace pldm
239