1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #pragma once
17 #include <ipmid/api.hpp>
18 #include <sdbusplus/message.hpp>
19 #include <sdbusplus/server/interface.hpp>
20 
21 /**
22  * @brief Response queue defines
23  */
24 constexpr int responseQueueMaxSize = 20;
25 
26 /**
27  * @brief Ipmb misc
28  */
29 constexpr uint8_t ipmbLunMask = 0x03;
30 constexpr uint8_t ipmbSeqMask = 0x3F;
31 constexpr uint8_t ipmbMeSlaveAddress = 0x2C;
32 constexpr uint8_t ipmbMeChannelNum = 1;
33 
34 /**
35  * @brief Ipmb getters
36  */
37 constexpr uint8_t ipmbNetFnGet(uint8_t netFnLun)
38 {
39     return netFnLun >> 2;
40 }
41 
42 constexpr uint8_t ipmbLunFromNetFnLunGet(uint8_t netFnLun)
43 {
44     return netFnLun & ipmbLunMask;
45 }
46 
47 constexpr uint8_t ipmbSeqGet(uint8_t seqNumLun)
48 {
49     return seqNumLun >> 2;
50 }
51 
52 constexpr uint8_t ipmbLunFromSeqLunGet(uint8_t seqNumLun)
53 {
54     return seqNumLun & ipmbLunMask;
55 }
56 
57 /**
58  * @brief Ipmb setters
59  */
60 constexpr uint8_t ipmbNetFnLunSet(uint8_t netFn, uint8_t lun)
61 {
62     return ((netFn << 2) | (lun & ipmbLunMask));
63 }
64 
65 constexpr uint8_t ipmbSeqLunSet(uint8_t seq, uint8_t lun)
66 {
67     return ((seq << 2) | (lun & ipmbLunMask));
68 }
69 
70 constexpr size_t ipmbMaxDataSize = 256;
71 constexpr size_t ipmbConnectionHeaderLength = 3;
72 constexpr size_t ipmbResponseDataHeaderLength = 4;
73 constexpr size_t ipmbRequestDataHeaderLength = 3;
74 constexpr size_t ipmbChecksum2StartOffset = 3;
75 constexpr size_t ipmbChecksumSize = 1;
76 constexpr size_t ipmbMinFrameLength = 7;
77 constexpr size_t ipmbMaxFrameLength = ipmbConnectionHeaderLength +
78                                       ipmbResponseDataHeaderLength +
79                                       ipmbChecksumSize + ipmbMaxDataSize;
80 
81 /**
82  * @brief Channel types
83  */
84 constexpr uint8_t targetChannelIpmb = 0x1;
85 constexpr uint8_t targetChannelIcmb10 = 0x2;
86 constexpr uint8_t targetChannelIcmb09 = 0x3;
87 constexpr uint8_t targetChannelLan = 0x4;
88 constexpr uint8_t targetChannelSerialModem = 0x5;
89 constexpr uint8_t targetChannelOtherLan = 0x6;
90 constexpr uint8_t targetChannelPciSmbus = 0x7;
91 constexpr uint8_t targetChannelSmbus10 = 0x8;
92 constexpr uint8_t targetChannelSmbus20 = 0x9;
93 constexpr uint8_t targetChannelSystemInterface = 0xC;
94 
95 /**
96  * @brief Channel modes
97  */
98 constexpr uint8_t modeNoTracking = 0x0;
99 constexpr uint8_t modeTrackRequest = 0x1;
100 constexpr uint8_t modeSendRaw = 0x2;
101 
102 /**
103  * @brief Command specific codes
104  */
105 constexpr ipmi_return_codes ipmiGetMessageCmdDataNotAvailable =
106     static_cast<ipmi_return_codes>(0x80);
107 
108 /**
109  * @brief Ipmb frame
110  */
111 typedef struct
112 {
113     /// @brief IPMB frame header
114     union
115     {
116         /// @brief IPMB request header
117         struct
118         {
119             /** @brief IPMB Connection Header Format */
120             uint8_t address;
121             uint8_t rsNetFnLUN;
122             uint8_t checksum1;
123             /** @brief IPMB Header */
124             uint8_t rqSA;
125             uint8_t rqSeqLUN;
126             uint8_t cmd;
127             uint8_t data[];
128         } Req;
129         /// @brief IPMB response header
130         struct
131         {
132             uint8_t address;
133             /** @brief IPMB Connection Header Format */
134             uint8_t rqNetFnLUN;
135             uint8_t checksum1;
136             /** @brief IPMB Header */
137             uint8_t rsSA;
138             uint8_t rsSeqLUN;
139             uint8_t cmd;
140             uint8_t completionCode;
141             uint8_t data[];
142         } Resp;
143     } Header;
144 } __attribute__((packed)) ipmbHeader;
145 
146 /**
147  * @brief Ipmb messages
148  */
149 struct IpmbRequest
150 {
151     uint8_t address;
152     uint8_t netFn;
153     uint8_t rsLun;
154     uint8_t rqSA;
155     uint8_t seq;
156     uint8_t rqLun;
157     uint8_t cmd;
158     std::vector<uint8_t> data;
159 
160     IpmbRequest(const ipmbHeader *ipmbBuffer, size_t bufferLength);
161 
162     void prepareRequest(sdbusplus::message::message &mesg);
163 };
164 
165 struct IpmbResponse
166 {
167     uint8_t address;
168     uint8_t netFn;
169     uint8_t rqLun;
170     uint8_t rsSA;
171     uint8_t seq;
172     uint8_t rsLun;
173     uint8_t cmd;
174     uint8_t completionCode;
175     std::vector<uint8_t> data;
176 
177     IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun, uint8_t rsSA,
178                  uint8_t seq, uint8_t rsLun, uint8_t cmd,
179                  uint8_t completionCode, std::vector<uint8_t> &inputData);
180 
181     void ipmbToi2cConstruct(uint8_t *buffer, size_t *bufferLength);
182 };
183 
184 /**
185  * @brief Send Message Request
186  */
187 typedef struct
188 {
189     uint8_t channelData;
190     uint8_t data[];
191 
192     constexpr uint8_t channelNumGet()
193     {
194         return (channelData & 0xF);
195     }
196 
197     constexpr uint8_t authenticationGet()
198     {
199         return ((channelData & 0x10) >> 4);
200     }
201 
202     constexpr uint8_t encryptionGet()
203     {
204         return ((channelData & 0x20) >> 5);
205     }
206 
207     constexpr uint8_t modeGet()
208     {
209         return ((channelData & 0xC0) >> 6);
210     }
211 } __attribute__((packed)) sSendMessageReq;
212 
213 /**
214  * @brief Get Message Response
215  */
216 typedef struct
217 {
218     uint8_t channelData;
219     uint8_t data[];
220 
221     constexpr void channelNumSet(uint8_t num)
222     {
223         channelData |= num & 0xF;
224     }
225 
226     constexpr void privilegeLvlSet(CommandPrivilege privLvl)
227     {
228         channelData |= static_cast<uint8_t>(privLvl) & 0xF0;
229     }
230 } __attribute__((packed)) sGetMessageRes;
231 
232 /**
233  * @brief Get Message Flags Response
234  */
235 constexpr uint8_t getMsgFlagReceiveMessageBit = 0;
236 constexpr uint8_t getMsgFlagEventMessageBit = 1;
237 constexpr uint8_t getMsgFlagWatchdogPreTimeOutBit = 3;
238 constexpr uint8_t getMsgFlagOEM0Bit = 5;
239 constexpr uint8_t getMsgFlagOEM1Bit = 6;
240 constexpr uint8_t getMsgFlagOEM2Bit = 7;
241 
242 /**
243  * @brief Clear Message Flags Request
244  */
245 typedef struct
246 {
247     uint8_t flags;
248 
249     constexpr uint8_t receiveMessageBitGet()
250     {
251         return (flags & 0x1);
252     }
253 
254     constexpr uint8_t eventMessageBitGet()
255     {
256         return ((flags & 0x2) >> 1);
257     }
258 
259     constexpr uint8_t watchdogTimeoutBitGet()
260     {
261         return ((flags & 0x8) >> 3);
262     }
263 
264     constexpr uint8_t oem0BitGet()
265     {
266         return ((flags & 0x20) >> 5);
267     }
268 
269     constexpr uint8_t oem1BitGet()
270     {
271         return ((flags & 0x40) >> 6);
272     }
273 
274     constexpr uint8_t oem2BitGet()
275     {
276         return ((flags & 0x80) >> 7);
277     }
278 } __attribute__((packed)) sClearMessageFlagsReq;
279 
280 /** @class Bridging
281  *
282  *  @brief Implement commands to support IPMI bridging.
283  */
284 class Bridging
285 {
286   public:
287     Bridging() = default;
288     std::size_t getResponseQueueSize();
289 
290     ipmi_return_codes sendMessageHandler(ipmi_request_t request,
291                                          ipmi_response_t response,
292                                          ipmi_data_len_t dataLen);
293 
294     ipmi_return_codes getMessageHandler(ipmi_request_t request,
295                                         ipmi_response_t response,
296                                         ipmi_data_len_t dataLen);
297 
298     ipmi_return_codes clearMessageFlagsHandler(ipmi_request_t request,
299                                                ipmi_response_t response,
300                                                ipmi_data_len_t dataLen);
301 
302     enum IpmiAppBridgingCmds
303     {
304         ipmiCmdClearMessageFlags = 0x30,
305         ipmiCmdGetMessage = 0x33,
306         ipmiCmdSendMessage = 0x34,
307     };
308 
309   private:
310     std::vector<IpmbResponse> responseQueue;
311 
312     ipmi_return_codes handleIpmbChannel(sSendMessageReq *sendMsgReq,
313                                         ipmi_response_t response,
314                                         ipmi_data_len_t dataLen);
315 };
316