Make use of new IPMI method call API
tested: checked communication by injecting I2C traffic via aardvark,
everything is working fine
aardvark<->I2C<->IPMB<->IPMI
Change-Id: Ie2a982e710473cfa594838328730b98affc2cb39
Signed-off-by: Dawid Frycki <dawid.frycki@intel.com>
diff --git a/ipmbbridged.cpp b/ipmbbridged.cpp
index b37c867..2018e28 100644
--- a/ipmbbridged.cpp
+++ b/ipmbbridged.cpp
@@ -34,7 +34,6 @@
*/
static constexpr const char *ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
static constexpr const char *ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
-static constexpr const char *hostIpmiIntf = "org.openbmc.HostIpmi";
static constexpr const char *ipmbDbusIntf = "org.openbmc.Ipmb";
boost::asio::io_service io;
@@ -55,7 +54,7 @@
IpmbRequest::IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun,
uint8_t rqSA, uint8_t seq, uint8_t rqLun, uint8_t cmd,
- std::vector<uint8_t> &inputData) :
+ const std::vector<uint8_t> &inputData) :
address(address),
netFn(netFn), rsLun(rsLun), rqSA(rqSA), seq(seq), rqLun(rqLun), cmd(cmd),
timer(io)
@@ -69,14 +68,6 @@
}
}
-void IpmbRequest::incomingMessageHandler()
-{
- sdbusplus::message::message mesg =
- conn->new_signal(ipmbObj, hostIpmiIntf, "ReceivedMessage");
- mesg.append(seq, netFn, rsLun, cmd, data);
- mesg.signal_send();
-}
-
void IpmbRequest::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
size_t bufferLength)
{
@@ -152,14 +143,6 @@
std::vector<uint8_t>(0));
}
-// TODO w/a to differentiate channel origin of incoming IPMI response: saving
-// channel number at two oldest unused bits of seq
-void IpmbRequest::addChannelToSeq(const ipmbChannelType &channelType)
-{
- uint8_t newSeq = (seq | ((static_cast<uint8_t>(channelType) & 0x3) << 6));
- seq = newSeq;
-}
-
/**
* @brief Ipmb response class methods
*/
@@ -171,7 +154,7 @@
IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
uint8_t rsSA, uint8_t seq, uint8_t rsLun,
uint8_t cmd, uint8_t completionCode,
- std::vector<uint8_t> &inputData) :
+ const std::vector<uint8_t> &inputData) :
address(address),
netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
completionCode(completionCode)
@@ -206,18 +189,20 @@
}
}
-int IpmbResponse::ipmbToi2cConstruct(std::vector<uint8_t> &buffer)
+std::shared_ptr<std::vector<uint8_t>> IpmbResponse::ipmbToi2cConstruct()
{
size_t bufferLength = data.size() + ipmbResponseDataHeaderLength +
ipmbConnectionHeaderLength + ipmbChecksumSize;
if (bufferLength > ipmbMaxFrameLength)
{
- return -1;
+ return nullptr;
}
- buffer.resize(bufferLength);
- auto ipmbBuffer = reinterpret_cast<IPMB_HEADER *>(buffer.data());
+ std::shared_ptr<std::vector<uint8_t>> buffer =
+ std::make_shared<std::vector<uint8_t>>(bufferLength);
+
+ auto ipmbBuffer = reinterpret_cast<IPMB_HEADER *>(buffer->data());
ipmbBuffer->Header.Resp.address = address;
ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
@@ -227,18 +212,18 @@
ipmbBuffer->Header.Resp.completionCode = completionCode;
ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
- buffer.data(), ipmbConnectionHeaderLength - ipmbChecksumSize);
+ buffer->data(), ipmbConnectionHeaderLength - ipmbChecksumSize);
if (data.size() > 0)
{
std::copy(data.begin(), data.end(), ipmbBuffer->Header.Resp.data);
}
- buffer[bufferLength - ipmbChecksumSize] =
- ipmbChecksumCompute(buffer.data() + ipmbChecksum2StartOffset,
+ (*buffer)[bufferLength - ipmbChecksumSize] =
+ ipmbChecksumCompute(buffer->data() + ipmbChecksum2StartOffset,
(ipmbResponseDataHeaderLength + data.size()));
- return 0;
+ return buffer;
}
bool IpmbCommandFilter::isBlocked(const uint8_t reqNetFn, const uint8_t cmd)
@@ -274,7 +259,7 @@
i2cMasterSocket,
boost::asio::buffer(buffer->data() + ipmbAddressSize,
buffer->size() - ipmbAddressSize),
- [this, buffer, retriesAttempted](const boost::system::error_code ec,
+ [this, buffer, retriesAttempted](const boost::system::error_code &ec,
size_t bytesSent) {
if (ec)
{
@@ -394,18 +379,15 @@
uint8_t seq = ipmbSeqGet(ipmbFrame->Header.Req.rqSeqLUN);
uint8_t lun =
ipmbLunFromSeqLunGet(ipmbFrame->Header.Req.rqSeqLUN);
- std::vector<uint8_t> data;
// prepare generic response
auto ipmbResponse =
IpmbResponse(ipmbRqSlaveAddress, ipmbRespNetFn(netFn), lun,
ipmbBmcSlaveAddress, seq, ipmbRsLun, cmd,
- ipmbIpmiInvalidCommand, data);
+ ipmbIpmiInvalidCmd, {});
- std::shared_ptr<std::vector<uint8_t>> buffer =
- std::make_shared<std::vector<uint8_t>>();
-
- if (ipmbResponse.ipmbToi2cConstruct(*buffer) == 0)
+ auto buffer = ipmbResponse.ipmbToi2cConstruct();
+ if (buffer)
{
ipmbResponseSend(buffer);
}
@@ -415,15 +397,79 @@
}
auto ipmbMessageReceived = IpmbRequest();
-
ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
- // TODO w/a to differentiate channel origin of incoming IPMI
- // response: extracting channel number from seq
- ipmbMessageReceived.addChannelToSeq(getChannelType());
+ std::map<std::string, std::variant<int>> options{
+ {"rqSA", ipmbAddressTo7BitSet(ipmbRqSlaveAddress)}};
+ using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
+ std::vector<uint8_t>>;
+ conn->async_method_call(
+ [this, rqLun{ipmbMessageReceived.rqLun},
+ seq{ipmbMessageReceived.seq}](const boost::system::error_code &ec,
+ const IpmiDbusRspType &response) {
+ const auto &[netfn, lun, cmd, cc, payload] = response;
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "processI2cEvent: error getting response from IPMI");
+ return;
+ }
- // send request to the client
- ipmbMessageReceived.incomingMessageHandler();
+ uint8_t rqSlaveAddress = getRqSlaveAddress();
+ uint8_t bmcSlaveAddress = getBmcSlaveAddress();
+
+ if (payload.size() > ipmbMaxDataSize)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "processI2cEvent: response exceeding maximum size");
+
+ // prepare generic response
+ auto ipmbResponse = IpmbResponse(
+ rqSlaveAddress, netfn, rqLun, bmcSlaveAddress, seq,
+ ipmbRsLun, cmd, ipmbIpmiCmdRespNotProvided, {});
+
+ auto buffer = ipmbResponse.ipmbToi2cConstruct();
+ if (buffer)
+ {
+ ipmbResponseSend(buffer);
+ }
+
+ return;
+ }
+
+ if (!(netfn & ipmbNetFnResponseMask))
+ {
+ // we are not expecting request here
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "processI2cEvent: got a request instead of response");
+ return;
+ }
+
+ // if command is not supported, add it to filter
+ if (cc == ipmbIpmiInvalidCmd)
+ {
+ addFilter(ipmbReqNetFnFromRespNetFn(netfn), cmd);
+ }
+
+ // payload is empty after constructor invocation
+ auto ipmbResponse =
+ IpmbResponse(rqSlaveAddress, netfn, rqLun, bmcSlaveAddress,
+ seq, lun, cmd, cc, payload);
+
+ auto buffer = ipmbResponse.ipmbToi2cConstruct();
+ if (!buffer)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "processI2cEvent: error constructing a request");
+ return;
+ }
+
+ ipmbResponseSend(buffer);
+ },
+ "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
+ "xyz.openbmc_project.Ipmi.Server", "execute",
+ ipmbMessageReceived.netFn, ipmbMessageReceived.rsLun,
+ ipmbMessageReceived.cmd, ipmbMessageReceived.data, options);
}
end:
@@ -656,62 +702,6 @@
return 0;
}
-/**
- * @brief Dbus callbacks
- */
-auto ipmbSendMessage = [](uint8_t seq, uint8_t netfn, uint8_t lun, uint8_t cmd,
- uint8_t cc, std::vector<uint8_t> &dataReceived) {
- int64_t status = -1;
- std::shared_ptr<std::vector<uint8_t>> buffer =
- std::make_shared<std::vector<uint8_t>>();
-
- if (dataReceived.size() > ipmbMaxDataSize)
- {
- return status;
- }
-
- if (netfn & ipmbNetFnResponseMask)
- {
- IpmbChannel *channel = getChannel(getChannelFromSeq(seq));
- if (channel == nullptr)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ipmbSendMessage: channel does not exist");
- return status;
- }
-
- // if command is not supported, add it to filter
- if (cc == ipmbIpmiInvalidCommand)
- {
- channel->addFilter(ipmbReqNetFnFromRespNetFn(netfn), cmd);
- }
-
- uint8_t rqSlaveAddress = channel->getRqSlaveAddress();
- uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
-
- // response received
- // dataReceived is empty after constructor invocation
- std::unique_ptr<IpmbResponse> ipmbMessageReceived =
- std::make_unique<IpmbResponse>(rqSlaveAddress, netfn, lun,
- bmcSlaveAddress, seq, lun, cmd, cc,
- dataReceived);
-
- status = ipmbMessageReceived->ipmbToi2cConstruct(*buffer);
- if (status != 0)
- {
- return status;
- }
-
- channel->ipmbResponseSend(buffer);
- return status;
- }
-
- // we are not expecting request here
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "ipmbSendMessage: got a request");
- return status;
-};
-
auto ipmbHandleRequest = [](boost::asio::yield_context yield,
uint8_t reqChannel, uint8_t netfn, uint8_t lun,
uint8_t cmd, std::vector<uint8_t> dataReceived) {
@@ -760,14 +750,10 @@
auto server = sdbusplus::asio::object_server(conn);
- std::shared_ptr<sdbusplus::asio::dbus_interface> ipmiIface =
- server.add_interface(ipmbObj, hostIpmiIntf);
std::shared_ptr<sdbusplus::asio::dbus_interface> ipmbIface =
server.add_interface(ipmbObj, ipmbDbusIntf);
- ipmiIface->register_method("sendMessage", std::move(ipmbSendMessage));
ipmbIface->register_method("sendRequest", std::move(ipmbHandleRequest));
- ipmiIface->initialize();
ipmbIface->initialize();
if (initializeChannels() < 0)
diff --git a/ipmbbridged.hpp b/ipmbbridged.hpp
index 317fdab..4d24790 100644
--- a/ipmbbridged.hpp
+++ b/ipmbbridged.hpp
@@ -145,13 +145,6 @@
me = 1
};
-// TODO w/a to differentiate channel origin of incoming IPMI response:
-// extracting channel number from 2 oldest bits of seq
-constexpr ipmbChannelType getChannelFromSeq(const uint8_t &seq)
-{
- return static_cast<ipmbChannelType>((seq & 0xC0) >> 6);
-}
-
/**
* @brief IpmbResponse declaration
*/
@@ -171,11 +164,11 @@
IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun, uint8_t rsSA,
uint8_t seq, uint8_t rsLun, uint8_t cmd,
- uint8_t completionCode, std::vector<uint8_t> &inputData);
+ uint8_t completionCode, const std::vector<uint8_t> &inputData);
void i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer, size_t bufferLength);
- int ipmbToi2cConstruct(std::vector<uint8_t> &buffer);
+ std::shared_ptr<std::vector<uint8_t>> ipmbToi2cConstruct();
};
/**
@@ -202,13 +195,11 @@
IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun, uint8_t rqSA,
uint8_t seq, uint8_t rqLun, uint8_t cmd,
- std::vector<uint8_t> &inputData);
+ const std::vector<uint8_t> &inputData);
IpmbRequest(const IpmbRequest &) = delete;
IpmbRequest &operator=(IpmbRequest const &) = delete;
- void incomingMessageHandler();
-
std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
returnMatchedResponse();
@@ -218,10 +209,6 @@
void i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer, size_t bufferLength);
int ipmbToi2cConstruct(std::vector<uint8_t> &buffer);
-
- // TODO w/a to differentiate channel origin of incoming IPMI response:
- // saving channel number at two oldest unused bits of seq
- void addChannelToSeq(const ipmbChannelType &channelType);
};
/**
@@ -247,7 +234,8 @@
* @brief Command filtering defines
*/
-constexpr uint8_t ipmbIpmiInvalidCommand = 0xC1;
+constexpr uint8_t ipmbIpmiInvalidCmd = 0xC1;
+constexpr uint8_t ipmbIpmiCmdRespNotProvided = 0xCE;
constexpr uint8_t ipmbReqNetFnFromRespNetFn(uint8_t reqNetFn)
{