google-ipmi-i2c: Refactor to use new version of OEM IPMI Handler
Use new IPMI OEM handler and cleanup the input arguments.
Change-Id: I26eff786b1b039fe06fdce723c70d58da3c8c6ea
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/i2c.cpp b/i2c.cpp
index 90891f5..76e3e93 100644
--- a/i2c.cpp
+++ b/i2c.cpp
@@ -26,9 +26,12 @@
#include <cerrno>
#include <cstdio>
#include <cstring>
+#include <ipmid/api-types.hpp>
+#include <ipmid/handler.hpp>
#include <ipmid/iana.hpp>
#include <ipmid/oemopenbmc.hpp>
#include <memory>
+#include <span>
namespace oem
{
@@ -48,7 +51,7 @@
struct ParsedStep
{
- const uint8_t* reqData;
+ std::span<const uint8_t> reqData;
size_t length;
DevAddr devAddr;
bool isRead;
@@ -67,41 +70,41 @@
std::array<ParsedStep, maxSteps> step;
};
-static ipmi_ret_t parseReqHdr(const uint8_t* reqBuf, size_t reqLen,
- size_t* bytesUsed, i2c::ParsedReq* req)
+ipmi::Cc parseReqHdr(std::span<const uint8_t> data, size_t* bytesUsed,
+ i2c::ParsedReq* req)
{
// Request header selects bus & flags for operation;
// additional bytes beyond are to be interpreted as steps.
- if (reqLen < *bytesUsed + requestHeaderLen)
+ if (data.size() < *bytesUsed + requestHeaderLen)
{
- std::fprintf(stderr, "i2c::parse reqLen=%zu?\n", reqLen);
- return IPMI_CC_REQ_DATA_LEN_INVALID;
+ std::fprintf(stderr, "i2c::parse reqLen=%zu?\n", data.size());
+ return ipmi::ccReqDataLenInvalid;
}
// Deserialize request header bytes.
- req->localbus = reqBuf[requestHeaderBus];
- auto reqFlags = reqBuf[requestHeaderFlags];
+ req->localbus = data[requestHeaderBus];
+ auto reqFlags = data[requestHeaderFlags];
*bytesUsed += requestHeaderLen;
// Decode flags.
req->usePec = !!(reqFlags & requestFlagsUsePec);
- return IPMI_CC_OK;
+ return ipmi::ccSuccess;
}
-static ipmi_ret_t parseReqStep(const uint8_t* reqBuf, size_t reqLen,
- size_t* bytesUsed, i2c::ParsedReq* req)
+ipmi::Cc parseReqStep(std::span<const uint8_t> data, size_t* bytesUsed,
+ i2c::ParsedReq* req)
{
- size_t bytesLeft = reqLen - *bytesUsed;
+ size_t bytesLeft = data.size() - *bytesUsed;
if (req->numSteps >= maxSteps || bytesLeft < stepHeaderLen)
{
std::fprintf(stderr, "i2c::parse[%zu] bytesLeft=%zu?\n", req->numSteps,
bytesLeft);
- return IPMI_CC_REQ_DATA_LEN_INVALID;
+ return ipmi::ccReqDataLenInvalid;
}
- const uint8_t* stepHdr = reqBuf + *bytesUsed;
+ const std::span<const uint8_t> stepHdr = data.subspan(*bytesUsed);
auto step = &req->step[req->numSteps++];
// Deserialize request step header bytes.
- uint8_t devAndDir = stepHdr[stepHeaderDevAndDir];
+ uint8_t devAndDir = data[stepHeaderDevAndDir];
uint8_t stepFlags = stepHdr[stepHeaderFlags];
step->length = stepHdr[stepHeaderParm];
bytesLeft -= stepHeaderLen;
@@ -129,40 +132,39 @@
{
std::fprintf(stderr, "i2c::parse[%zu] bytesLeft=%zu, parm=%zu?\n",
req->numSteps, bytesLeft, step->length);
- return IPMI_CC_REQ_DATA_LEN_INVALID;
+ return ipmi::ccReqDataLenInvalid;
}
- step->reqData = reqBuf + *bytesUsed;
+ step->reqData = data.subspan(*bytesUsed);
*bytesUsed += step->length;
}
- return IPMI_CC_OK;
+ return ipmi::ccSuccess;
}
// Parse i2c request.
-static ipmi_ret_t parse(const uint8_t* reqBuf, size_t reqLen,
- i2c::ParsedReq* req)
+ipmi::Cc parse(std::span<const uint8_t> data, i2c::ParsedReq* req)
{
size_t bytesUsed = 0;
- auto rc = parseReqHdr(reqBuf, reqLen, &bytesUsed, req);
- if (rc != IPMI_CC_OK)
+ auto rc = parseReqHdr(data, &bytesUsed, req);
+ if (rc != ipmi::ccSuccess)
{
return rc;
}
do
{
- rc = parseReqStep(reqBuf, reqLen, &bytesUsed, req);
- if (rc != IPMI_CC_OK)
+ rc = parseReqStep(data, &bytesUsed, req);
+ if (rc != ipmi::ccSuccess)
{
return rc;
}
- } while (bytesUsed < reqLen);
- return IPMI_CC_OK;
+ } while (bytesUsed < data.size());
+ return ipmi::ccSuccess;
}
// Convert parsed request to I2C messages.
-static ipmi_ret_t buildI2cMsgs(const i2c::ParsedReq& req,
- std::unique_ptr<i2c::BlockBuf> rxBuf[],
- struct i2c_msg msgs[],
- struct i2c_rdwr_ioctl_data* msgset)
+static ipmi::Cc buildI2cMsgs(const i2c::ParsedReq& req,
+ std::unique_ptr<i2c::BlockBuf> rxBuf[],
+ struct i2c_msg msgs[],
+ struct i2c_rdwr_ioctl_data* msgset)
{
size_t minReplyLen = 0;
@@ -176,7 +178,7 @@
{
msg->flags = 0;
msg->len = step.length;
- msg->buf = const_cast<uint8_t*>(step.reqData);
+ msg->buf = const_cast<uint8_t*>(step.reqData.data());
continue;
}
rxBuf[i] = std::make_unique<i2c::BlockBuf>();
@@ -209,7 +211,7 @@
if (minReplyLen > i2c::largestReply)
{
std::fprintf(stderr, "I2c::transfer minReplyLen=%zu?\n", minReplyLen);
- return IPMI_CC_RESPONSE_ERROR; // Won't fit in response message
+ return ipmi::ccResponseError; // Won't fit in response message
}
#ifdef __IPMI_DEBUG__
@@ -221,7 +223,7 @@
}
#endif
- return IPMI_CC_OK;
+ return ipmi::ccSuccess;
}
static int openBus(BusId localbus)
@@ -241,17 +243,14 @@
} // namespace i2c
-ipmi_ret_t I2c::transfer(ipmi_cmd_t, const uint8_t* reqBuf, uint8_t* replyBuf,
- size_t* dataLen)
+Resp I2c::transfer(::ipmi::Context::ptr, std::span<const uint8_t> data)
{
// Parse message header.
- auto reqLen = *dataLen;
- *dataLen = 0;
i2c::ParsedReq req = {};
- auto rc = parse(reqBuf, reqLen, &req);
- if (rc != IPMI_CC_OK)
+ auto rc = parse(data, &req);
+ if (rc != ipmi::ccSuccess)
{
- return rc;
+ return ipmi::response(rc);
}
// Build full msgset
@@ -262,16 +261,16 @@
.nmsgs = 0,
};
rc = buildI2cMsgs(req, rxBuf, msgs, &msgset);
- if (rc != IPMI_CC_OK)
+ if (rc != ipmi::ccSuccess)
{
- return rc;
+ return ipmi::response(rc);
}
// Try to open i2c bus
int busFd = i2c::openBus(req.localbus);
if (busFd < 0)
{
- return IPMI_CC_UNSPECIFIED_ERROR;
+ return ipmi::responseUnspecifiedError();
}
int ioError = ioctl(busFd, I2C_RDWR, &msgset);
@@ -280,11 +279,11 @@
if (ioError < 0)
{
std::fprintf(stderr, "I2c::transfer I2C_RDWR ioError=%d?\n", ioError);
- return IPMI_CC_UNSPECIFIED_ERROR; // I2C_RDWR I/O error
+ return ipmi::responseUnspecifiedError(); // I2C_RDWR I/O error
}
// If we read any data, append it, in the order we read it.
- uint8_t* nextReplyByte = replyBuf;
+ std::vector<uint8_t> output;
size_t replyLen = 0;
for (size_t i = 0; i < req.numSteps; ++i)
{
@@ -299,30 +298,32 @@
{
std::fprintf(stderr, "I2c::transfer[%zu] replyLen=%zu?\n", i,
replyLen);
- return IPMI_CC_RESPONSE_ERROR; // Won't fit in response message
+ return ipmi::responseUnspecifiedError(); // Won't fit in
+ // response message
}
- std::memcpy(nextReplyByte, msg->buf, lenRead);
- nextReplyByte += lenRead;
+ output.resize(output.size() + lenRead);
+ std::memcpy(output.data() + output.size() - lenRead, msg->buf,
+ lenRead);
}
}
- *dataLen = replyLen;
- return IPMI_CC_OK;
+ return ::ipmi::responseSuccess(output);
}
-void I2c::registerWith(Router* oemRouter)
+void I2c::registerOemRouter()
{
- Handler f = [this](ipmi_cmd_t cmd, const uint8_t* reqBuf, uint8_t* replyBuf,
- size_t* dataLen) {
- return transfer(cmd, reqBuf, replyBuf, dataLen);
+ auto handler = [this](ipmi::Context::ptr ctx, std::vector<uint8_t> data) {
+ return transfer(ctx, data);
};
std::fprintf(stderr, "Registering OEM:[%#08X], Cmd:[%#04X] for I2C\n",
googOemNumber, Cmd::i2cCmd);
- oemRouter->registerHandler(googOemNumber, Cmd::i2cCmd, f);
+ ipmi::registerOemHandler(::ipmi::prioOemBase, oem::googOemNumber,
+ Cmd::i2cCmd, ::ipmi::Privilege::User, handler);
std::fprintf(stderr, "Registering OEM:[%#08X], Cmd:[%#04X] for I2C\n",
obmcOemNumber, Cmd::i2cCmd);
- oemRouter->registerHandler(obmcOemNumber, Cmd::i2cCmd, f);
+ ipmi::registerOemHandler(::ipmi::prioOemBase, oem::obmcOemNumber,
+ Cmd::i2cCmd, ::ipmi::Privilege::User, handler);
}
namespace i2c
@@ -334,7 +335,7 @@
void setupGlobalOemI2c()
{
globalOemI2c = std::make_unique<I2c>();
- globalOemI2c->registerWith(oem::mutableRouter());
+ globalOemI2c->registerOemRouter();
}
} // namespace i2c
} // namespace oem