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