IPMI OEM Get BIC GPIO State
Register an IPMI command handler - NetFn: 0x38 Cmd: 0x03.
Send command through IPMB to get BIC GPIO state.
Add Meta IANA definition for future utilization.
Limitation:
1. Could only get the state of BIC GPIOs which are configured as GPIO
2. Couldn't get all BIC GPIO states
Test Case:
Call IPMI OEM get BIC GPIO state
Signed-off-by: Bonnie Lo <Bonnie_Lo@wiwynn.com>
Change-Id: Idda8d4c532b2971c14662e7b34ea101cf584fa22
diff --git a/include/biccommands.hpp b/include/biccommands.hpp
index 5493304..e8742d1 100644
--- a/include/biccommands.hpp
+++ b/include/biccommands.hpp
@@ -1,9 +1,10 @@
-// Command for getting device id
-constexpr uint8_t cmdOemBicInfo = 0x01;
-
-// Command for getting post code
-constexpr uint8_t cmdOemSendPostBufferToBMC = 0x08;
+enum class fb_bic_cmds : uint8_t
+{
+ CMD_OEM_BIC_INFO = 0x1,
+ CMD_OEM_GET_BIC_GPIO_STATE = 0x3,
+ CMD_OEM_SEND_POST_BUFFER_TO_BMC = 0x8,
+};
const char* dbusObj = "/xyz/openbmc_project/state/boot/raw";
diff --git a/include/commandutils.hpp b/include/commandutils.hpp
index e318f13..d51c0e8 100644
--- a/include/commandutils.hpp
+++ b/include/commandutils.hpp
@@ -22,6 +22,10 @@
static constexpr bool debug = false;
+using IanaType = std::array<uint8_t, 3>;
+
+static constexpr IanaType iana = {0x15, 0xA0, 0x0}; // Meta's IANA
+
static void instances(std::string s, std::vector<std::string>& host)
{
size_t pos = 0;
diff --git a/src/biccommands.cpp b/src/biccommands.cpp
index 0813593..5212452 100644
--- a/src/biccommands.cpp
+++ b/src/biccommands.cpp
@@ -37,15 +37,18 @@
extern message::Response::ptr executeIpmiCommand(message::Request::ptr);
+int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
+ std::vector<uint8_t>&);
+
//----------------------------------------------------------------------
// ipmiOemBicHandler (IPMI/Section - ) (CMD_OEM_BIC_INFO)
// This Function will handle BIC request for netfn=0x38 and cmd=1
// send the response back to the sender.
//----------------------------------------------------------------------
-ipmi::RspType<std::array<uint8_t, 3>, uint8_t, uint2_t, uint6_t, uint8_t,
- uint8_t, ipmi::message::Payload>
- ipmiOemBicHandler(ipmi::Context::ptr ctx, std::array<uint8_t, 3> iana,
+ipmi::RspType<IanaType, uint8_t, uint2_t, uint6_t, uint8_t, uint8_t,
+ ipmi::message::Payload>
+ ipmiOemBicHandler(ipmi::Context::ptr ctx, IanaType reqIana,
uint8_t interface, uint2_t lun, uint6_t netFnReq,
uint8_t cmdReq, SecureBuffer data)
{
@@ -63,7 +66,7 @@
res = ipmi::executeIpmiCommand(req);
// sending the response with headers and payload
- return ipmi::responseSuccess(iana, interface, lun, ++netFnReq, cmdReq,
+ return ipmi::responseSuccess(reqIana, interface, lun, ++netFnReq, cmdReq,
res->cc, res->payload);
}
@@ -73,9 +76,10 @@
// netfn=0x38 and cmd=0x08 send the response back to the sender.
//----------------------------------------------------------------------
-ipmi::RspType<std::array<uint8_t, 3>>
- ipmiOemPostCodeHandler(ipmi::Context::ptr ctx, std::array<uint8_t, 3> iana,
- uint8_t dataLen, std::vector<uint8_t> data)
+ipmi::RspType<IanaType> ipmiOemPostCodeHandler(ipmi::Context::ptr ctx,
+ IanaType reqIana,
+ uint8_t dataLen,
+ std::vector<uint8_t> data)
{
// creating bus connection
auto conn = getSdBus();
@@ -113,7 +117,42 @@
}
}
- return ipmi::responseSuccess(iana);
+ return ipmi::responseSuccess(reqIana);
+}
+
+//----------------------------------------------------------------------
+// ipmiOemGetBicGpioState (CMD_OEM_GET_BIC_GPIO_STATE)
+// This Function will handle BIC GPIO stats for
+// netfn=0x38 and cmd=0x03 send the response back to the sender.
+//----------------------------------------------------------------------
+
+ipmi::RspType<IanaType, std::vector<uint8_t>>
+ ipmiOemGetBicGpioState(ipmi::Context::ptr ctx, std::vector<uint8_t> reqIana)
+{
+ std::vector<uint8_t> respData;
+
+ if (std::equal(reqIana.begin(), reqIana.end(), iana.begin()) == false)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Invalid IANA number");
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
+
+ if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqIana, respData))
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ std::vector<uint8_t> gpioState;
+ IanaType respIana;
+
+ auto r =
+ std::ranges::copy_n(respData.begin(), iana.size(), respIana.begin()).in;
+ std::copy(r, respData.end(), std::back_inserter(gpioState));
+
+ return ipmi::responseSuccess(respIana, gpioState);
}
[[maybe_unused]] static void registerBICFunctions(void)
@@ -123,11 +162,16 @@
"Registering BIC commands");
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
- cmdOemBicInfo, ipmi::Privilege::User,
- ipmiOemBicHandler);
- ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
- cmdOemSendPostBufferToBMC, ipmi::Privilege::User,
- ipmiOemPostCodeHandler);
+ static_cast<Cmd>(fb_bic_cmds::CMD_OEM_BIC_INFO),
+ ipmi::Privilege::User, ipmiOemBicHandler);
+ ipmi::registerHandler(
+ ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
+ static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SEND_POST_BUFFER_TO_BMC),
+ ipmi::Privilege::User, ipmiOemPostCodeHandler);
+ ipmi::registerHandler(
+ ipmi::prioOemBase, ipmi::netFnOemFive,
+ static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_BIC_GPIO_STATE),
+ ipmi::Privilege::User, ipmiOemGetBicGpioState);
return;
}