xref: /openbmc/ipmbbridge/ipmbbridged.hpp (revision 8edcf1a04d7fcd74fb8917cd4075b2bca1b16bb3)
1a642a948SDawid Frycki /* Copyright 2018 Intel
2a642a948SDawid Frycki  *
3a642a948SDawid Frycki  * Licensed under the Apache License, Version 2.0 (the "License");
4a642a948SDawid Frycki  * you may not use this file except in compliance with the License.
5a642a948SDawid Frycki  * You may obtain a copy of the License at
6a642a948SDawid Frycki  *
7a642a948SDawid Frycki  *    http://www.apache.org/licenses/LICENSE-2.0
8a642a948SDawid Frycki  *
9a642a948SDawid Frycki  *  Unless required by applicable law or agreed to in writing, software
10a642a948SDawid Frycki  *  distributed under the License is distributed on an "AS IS" BASIS,
11a642a948SDawid Frycki  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a642a948SDawid Frycki  *  See the License for the specific language governing permissions and
13a642a948SDawid Frycki  *  limitations under the License.
14a642a948SDawid Frycki  */
15a642a948SDawid Frycki 
16a642a948SDawid Frycki #include "ipmbdefines.hpp"
17a642a948SDawid Frycki 
18a642a948SDawid Frycki #include <boost/container/flat_set.hpp>
19a642a948SDawid Frycki #include <optional>
20a642a948SDawid Frycki #include <sdbusplus/asio/object_server.hpp>
21a642a948SDawid Frycki #include <sdbusplus/message.hpp>
22a642a948SDawid Frycki #include <vector>
23a642a948SDawid Frycki 
24a642a948SDawid Frycki #ifndef IPMBBRIDGED_HPP
25a642a948SDawid Frycki #define IPMBBRIDGED_HPP
26a642a948SDawid Frycki 
27a642a948SDawid Frycki /**
28a642a948SDawid Frycki  * @brief Ipmb return status codes (sendRequest API call)
29a642a948SDawid Frycki  */
30a642a948SDawid Frycki enum class ipmbResponseStatus
31a642a948SDawid Frycki {
32a642a948SDawid Frycki     success = 0,
33a642a948SDawid Frycki     error = 1,
34a642a948SDawid Frycki     invalid_param = 2,
35a642a948SDawid Frycki     busy = 3,
36a642a948SDawid Frycki     timeout = 4,
37a642a948SDawid Frycki };
38a642a948SDawid Frycki 
39a642a948SDawid Frycki /**
40a642a948SDawid Frycki  * @brief Ipmb outstanding requests defines
41a642a948SDawid Frycki  */
42a642a948SDawid Frycki constexpr int ipmbMaxOutstandingRequestsCount = 64;
43a642a948SDawid Frycki constexpr int ipmbNumberOfTries = 6;
44a642a948SDawid Frycki constexpr uint64_t ipmbRequestRetryTimeout = 250; // ms
45a642a948SDawid Frycki 
46a642a948SDawid Frycki /**
47a642a948SDawid Frycki  * @brief Ipmb I2C communication
48a642a948SDawid Frycki  */
49a642a948SDawid Frycki constexpr uint8_t ipmbI2cNumberOfRetries = 2;
50a642a948SDawid Frycki 
51a642a948SDawid Frycki /**
52a642a948SDawid Frycki  * @brief Ipmb defines
53a642a948SDawid Frycki  */
54a642a948SDawid Frycki constexpr size_t ipmbMaxDataSize = 256;
55a642a948SDawid Frycki constexpr size_t ipmbConnectionHeaderLength = 3;
56a642a948SDawid Frycki constexpr size_t ipmbResponseDataHeaderLength = 4;
57a642a948SDawid Frycki constexpr size_t ipmbRequestDataHeaderLength = 3;
58a642a948SDawid Frycki constexpr size_t ipmbAddressSize = 1;
59a642a948SDawid Frycki constexpr size_t ipmbChecksumSize = 1;
60a642a948SDawid Frycki constexpr size_t ipmbChecksum2StartOffset = 3;
61a642a948SDawid Frycki constexpr size_t ipmbMinFrameLength = 7;
62a642a948SDawid Frycki constexpr size_t ipmbMaxFrameLength = ipmbConnectionHeaderLength +
63a642a948SDawid Frycki                                       ipmbResponseDataHeaderLength +
64a642a948SDawid Frycki                                       ipmbChecksumSize + ipmbMaxDataSize;
65a642a948SDawid Frycki 
66a642a948SDawid Frycki /**
67a642a948SDawid Frycki  * @brief Ipmb misc
68a642a948SDawid Frycki  */
69a642a948SDawid Frycki constexpr uint8_t ipmbNetFnResponseMask = 0x01;
70a642a948SDawid Frycki constexpr uint8_t ipmbLunMask = 0x03;
71a642a948SDawid Frycki constexpr uint8_t ipmbSeqMask = 0x3F;
72a642a948SDawid Frycki constexpr uint8_t ipmbRsLun = 0x0;
73a642a948SDawid Frycki 
74a642a948SDawid Frycki /**
75a642a948SDawid Frycki  * @brief Ipmb setters
76a642a948SDawid Frycki  */
77a642a948SDawid Frycki constexpr uint8_t ipmbNetFnLunSet(uint8_t netFn, uint8_t lun)
78a642a948SDawid Frycki {
79a642a948SDawid Frycki     return ((netFn << 2) | (lun & ipmbLunMask));
80a642a948SDawid Frycki }
81a642a948SDawid Frycki 
82a642a948SDawid Frycki constexpr uint8_t ipmbSeqLunSet(uint8_t seq, uint8_t lun)
83a642a948SDawid Frycki {
84a642a948SDawid Frycki     return ((seq << 2) | (lun & ipmbLunMask));
85a642a948SDawid Frycki }
86a642a948SDawid Frycki 
87a642a948SDawid Frycki constexpr uint8_t ipmbAddressTo7BitSet(uint8_t address)
88a642a948SDawid Frycki {
89a642a948SDawid Frycki     return address >> 1;
90a642a948SDawid Frycki }
91a642a948SDawid Frycki 
92a642a948SDawid Frycki constexpr uint8_t ipmbRespNetFn(uint8_t netFn)
93a642a948SDawid Frycki {
94a642a948SDawid Frycki     return netFn |= 1;
95a642a948SDawid Frycki }
96a642a948SDawid Frycki 
97a642a948SDawid Frycki /**
98a642a948SDawid Frycki  * @brief Ipmb getters
99a642a948SDawid Frycki  */
100a642a948SDawid Frycki constexpr uint8_t ipmbNetFnGet(uint8_t netFnLun)
101a642a948SDawid Frycki {
102a642a948SDawid Frycki     return netFnLun >> 2;
103a642a948SDawid Frycki }
104a642a948SDawid Frycki 
105a642a948SDawid Frycki constexpr uint8_t ipmbLunFromNetFnLunGet(uint8_t netFnLun)
106a642a948SDawid Frycki {
107a642a948SDawid Frycki     return netFnLun & ipmbLunMask;
108a642a948SDawid Frycki }
109a642a948SDawid Frycki 
110a642a948SDawid Frycki constexpr uint8_t ipmbSeqGet(uint8_t seqNumLun)
111a642a948SDawid Frycki {
112a642a948SDawid Frycki     return seqNumLun >> 2;
113a642a948SDawid Frycki }
114a642a948SDawid Frycki 
115a642a948SDawid Frycki constexpr uint8_t ipmbLunFromSeqLunGet(uint8_t seqNumLun)
116a642a948SDawid Frycki {
117a642a948SDawid Frycki     return seqNumLun & ipmbLunMask;
118a642a948SDawid Frycki }
119a642a948SDawid Frycki 
120a642a948SDawid Frycki /**
121a642a948SDawid Frycki  * @brief Ipmb checkers
122a642a948SDawid Frycki  */
123a642a948SDawid Frycki constexpr bool ipmbIsResponse(IPMB_HEADER *ipmbHeader)
124a642a948SDawid Frycki {
125a642a948SDawid Frycki     return ipmbNetFnGet(ipmbHeader->Header.Resp.rqNetFnLUN) &
126a642a948SDawid Frycki            ipmbNetFnResponseMask;
127a642a948SDawid Frycki }
128a642a948SDawid Frycki 
129a642a948SDawid Frycki /**
130a642a948SDawid Frycki  * @brief Ipmb request state
131a642a948SDawid Frycki  */
132a642a948SDawid Frycki enum class ipmbRequestState
133a642a948SDawid Frycki {
134a642a948SDawid Frycki     invalid,
135a642a948SDawid Frycki     valid,
136a642a948SDawid Frycki     matched,
137a642a948SDawid Frycki };
138a642a948SDawid Frycki 
139a642a948SDawid Frycki /**
140a642a948SDawid Frycki  * @brief Channel types
141a642a948SDawid Frycki  */
142a642a948SDawid Frycki enum class ipmbChannelType
143a642a948SDawid Frycki {
144a642a948SDawid Frycki     ipmb = 0,
145a642a948SDawid Frycki     me = 1
146a642a948SDawid Frycki };
147a642a948SDawid Frycki 
148a642a948SDawid Frycki /**
149a642a948SDawid Frycki  * @brief IpmbResponse declaration
150a642a948SDawid Frycki  */
151a642a948SDawid Frycki struct IpmbResponse
152a642a948SDawid Frycki {
153a642a948SDawid Frycki     uint8_t address;
154a642a948SDawid Frycki     uint8_t netFn;
155a642a948SDawid Frycki     uint8_t rqLun;
156a642a948SDawid Frycki     uint8_t rsSA;
157a642a948SDawid Frycki     uint8_t seq;
158a642a948SDawid Frycki     uint8_t rsLun;
159a642a948SDawid Frycki     uint8_t cmd;
160a642a948SDawid Frycki     uint8_t completionCode;
161a642a948SDawid Frycki     std::vector<uint8_t> data;
162a642a948SDawid Frycki 
163a642a948SDawid Frycki     IpmbResponse();
164a642a948SDawid Frycki 
165a642a948SDawid Frycki     IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun, uint8_t rsSA,
166a642a948SDawid Frycki                  uint8_t seq, uint8_t rsLun, uint8_t cmd,
1678188d765SDawid Frycki                  uint8_t completionCode, const std::vector<uint8_t> &inputData);
168a642a948SDawid Frycki 
169a642a948SDawid Frycki     void i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer, size_t bufferLength);
170a642a948SDawid Frycki 
1718188d765SDawid Frycki     std::shared_ptr<std::vector<uint8_t>> ipmbToi2cConstruct();
172a642a948SDawid Frycki };
173a642a948SDawid Frycki 
174a642a948SDawid Frycki /**
175a642a948SDawid Frycki  * @brief IpmbRequest declaration
176a642a948SDawid Frycki  */
177a642a948SDawid Frycki struct IpmbRequest
178a642a948SDawid Frycki {
179a642a948SDawid Frycki     uint8_t address;
180a642a948SDawid Frycki     uint8_t netFn;
181a642a948SDawid Frycki     uint8_t rsLun;
182a642a948SDawid Frycki     uint8_t rqSA;
183a642a948SDawid Frycki     uint8_t seq;
184a642a948SDawid Frycki     uint8_t rqLun;
185a642a948SDawid Frycki     uint8_t cmd;
186a642a948SDawid Frycki     std::vector<uint8_t> data;
187a642a948SDawid Frycki 
188a642a948SDawid Frycki     size_t dataLength;
189a642a948SDawid Frycki     ipmbRequestState state;
190a642a948SDawid Frycki     std::optional<boost::asio::steady_timer> timer;
191a642a948SDawid Frycki     std::unique_ptr<IpmbResponse> matchedResponse;
192a642a948SDawid Frycki 
193a642a948SDawid Frycki     // creates empty request with empty timer object
194a642a948SDawid Frycki     IpmbRequest();
195a642a948SDawid Frycki 
196a642a948SDawid Frycki     IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun, uint8_t rqSA,
197a642a948SDawid Frycki                 uint8_t seq, uint8_t rqLun, uint8_t cmd,
1988188d765SDawid Frycki                 const std::vector<uint8_t> &inputData);
199a642a948SDawid Frycki 
200a642a948SDawid Frycki     IpmbRequest(const IpmbRequest &) = delete;
201a642a948SDawid Frycki     IpmbRequest &operator=(IpmbRequest const &) = delete;
202a642a948SDawid Frycki 
203a642a948SDawid Frycki     std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
204a642a948SDawid Frycki         returnMatchedResponse();
205a642a948SDawid Frycki 
206a642a948SDawid Frycki     std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
207a642a948SDawid Frycki         returnStatusResponse(int status);
208a642a948SDawid Frycki 
209a642a948SDawid Frycki     void i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer, size_t bufferLength);
210a642a948SDawid Frycki 
211a642a948SDawid Frycki     int ipmbToi2cConstruct(std::vector<uint8_t> &buffer);
212a642a948SDawid Frycki };
213a642a948SDawid Frycki 
214a642a948SDawid Frycki /**
215a642a948SDawid Frycki  * @brief Command filtering class declaration
216a642a948SDawid Frycki  *
217a642a948SDawid Frycki  * This feature provides simple mechanism for filtering out commands - which are
218a642a948SDawid Frycki  * not implemented in IPMI - on IPMB level, in order to reduce DBus traffic
219a642a948SDawid Frycki  */
220a642a948SDawid Frycki class IpmbCommandFilter
221a642a948SDawid Frycki {
222a642a948SDawid Frycki   public:
223a642a948SDawid Frycki     // function checking if netFn & cmd combination exist in blocked command
224a642a948SDawid Frycki     // list
225a642a948SDawid Frycki     bool isBlocked(const uint8_t reqNetFn, const uint8_t cmd);
226a642a948SDawid Frycki     // function adding netfFn & cmd combination to the blocked command list
227a642a948SDawid Frycki     void addFilter(const uint8_t reqNetFn, const uint8_t cmd);
228a642a948SDawid Frycki 
229a642a948SDawid Frycki   private:
230a642a948SDawid Frycki     boost::container::flat_set<std::pair<uint8_t, uint8_t>> unhandledCommands;
231a642a948SDawid Frycki };
232a642a948SDawid Frycki 
233a642a948SDawid Frycki /**
234a642a948SDawid Frycki  * @brief Command filtering defines
235a642a948SDawid Frycki  */
236a642a948SDawid Frycki 
2378188d765SDawid Frycki constexpr uint8_t ipmbIpmiInvalidCmd = 0xC1;
2388188d765SDawid Frycki constexpr uint8_t ipmbIpmiCmdRespNotProvided = 0xCE;
239a642a948SDawid Frycki 
240a642a948SDawid Frycki constexpr uint8_t ipmbReqNetFnFromRespNetFn(uint8_t reqNetFn)
241a642a948SDawid Frycki {
242a642a948SDawid Frycki     return reqNetFn & ~ipmbNetFnResponseMask;
243a642a948SDawid Frycki }
244a642a948SDawid Frycki 
245a642a948SDawid Frycki /**
246a642a948SDawid Frycki  * @brief IpmbChannel class declaration
247a642a948SDawid Frycki  */
248a642a948SDawid Frycki class IpmbChannel
249a642a948SDawid Frycki {
250a642a948SDawid Frycki   public:
251a642a948SDawid Frycki     IpmbChannel(boost::asio::io_service &io, uint8_t ipmbBmcSlaveAddress,
252a642a948SDawid Frycki                 uint8_t ipmbRqSlaveAddress, ipmbChannelType type,
253a642a948SDawid Frycki                 std::shared_ptr<IpmbCommandFilter> commandFilter);
254a642a948SDawid Frycki 
255a642a948SDawid Frycki     IpmbChannel(const IpmbChannel &) = delete;
256a642a948SDawid Frycki     IpmbChannel &operator=(IpmbChannel const &) = delete;
257a642a948SDawid Frycki 
258a642a948SDawid Frycki     int ipmbChannelInit(const char *ipmbI2cSlave, const char *ipmbI2cMaster);
259a642a948SDawid Frycki 
260*8edcf1a0SQiang XU     int ipmbChannelUpdateSlaveAddress(const uint8_t newBmcSlaveAddr);
261*8edcf1a0SQiang XU 
262a642a948SDawid Frycki     bool seqNumGet(uint8_t &seq);
263a642a948SDawid Frycki 
264a642a948SDawid Frycki     ipmbChannelType getChannelType();
265a642a948SDawid Frycki 
266*8edcf1a0SQiang XU     uint8_t getBusId();
267*8edcf1a0SQiang XU 
268a642a948SDawid Frycki     uint8_t getBmcSlaveAddress();
269a642a948SDawid Frycki 
270a642a948SDawid Frycki     uint8_t getRqSlaveAddress();
271a642a948SDawid Frycki 
272a642a948SDawid Frycki     void addFilter(const uint8_t respNetFn, const uint8_t cmd);
273a642a948SDawid Frycki 
274a642a948SDawid Frycki     void processI2cEvent();
275a642a948SDawid Frycki 
276a642a948SDawid Frycki     void ipmbResponseSend(std::shared_ptr<std::vector<uint8_t>> buffer,
277a642a948SDawid Frycki                           size_t retriesAttempted);
278a642a948SDawid Frycki 
279a642a948SDawid Frycki     std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
280a642a948SDawid Frycki         requestAdd(boost::asio::yield_context &yield,
281a642a948SDawid Frycki                    std::shared_ptr<IpmbRequest> requestToSend);
282a642a948SDawid Frycki 
283a642a948SDawid Frycki   private:
284a642a948SDawid Frycki     boost::asio::ip::tcp::socket i2cSlaveSocket;
285a642a948SDawid Frycki     boost::asio::posix::stream_descriptor i2cMasterSocket;
286a642a948SDawid Frycki 
287a642a948SDawid Frycki     int ipmbi2cMasterFd;
288a642a948SDawid Frycki     int ipmbi2cSlaveFd;
289a642a948SDawid Frycki 
290a642a948SDawid Frycki     uint8_t ipmbBmcSlaveAddress;
291a642a948SDawid Frycki     uint8_t ipmbRqSlaveAddress;
292*8edcf1a0SQiang XU     uint8_t ipmbBusId;
293a642a948SDawid Frycki 
294a642a948SDawid Frycki     ipmbChannelType type;
295a642a948SDawid Frycki 
296a642a948SDawid Frycki     std::shared_ptr<IpmbCommandFilter> commandFilter;
297a642a948SDawid Frycki 
298a642a948SDawid Frycki     // array storing outstanding requests
299a642a948SDawid Frycki     std::array<std::shared_ptr<IpmbRequest>, ipmbMaxOutstandingRequestsCount>
300a642a948SDawid Frycki         outstandingRequests;
301a642a948SDawid Frycki 
302a642a948SDawid Frycki     void requestTimerCallback(std::shared_ptr<IpmbRequest> request,
303a642a948SDawid Frycki                               std::shared_ptr<std::vector<uint8_t>> buffer);
304a642a948SDawid Frycki 
305a642a948SDawid Frycki     void responseMatch(std::unique_ptr<IpmbResponse> &response);
306a642a948SDawid Frycki 
307a642a948SDawid Frycki     void makeRequestInvalid(IpmbRequest &request);
308a642a948SDawid Frycki 
309a642a948SDawid Frycki     void makeRequestValid(std::shared_ptr<IpmbRequest> request);
310a642a948SDawid Frycki };
311a642a948SDawid Frycki 
312a642a948SDawid Frycki #endif
313