Add DCMI Get/Set Management Controller Id String
Resolves openbmc/openbmc#1855
Change-Id: I878c7bcb1ea8b46cd3e932b1cbb2290fe612f652
Signed-off-by: Vladislav Vovchenko <vlad.vovchenko93@gmail.com>
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index 5df6559..806ddd0 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -207,6 +207,17 @@
}
}
+std::string getHostName(void)
+{
+ sdbusplus::bus::bus bus{ ipmid_get_sd_bus_connection() };
+
+ auto service = ipmi::getService(bus, networkConfigIntf, networkConfigObj);
+ auto value = ipmi::getDbusProperty(bus, service,
+ networkConfigObj, networkConfigIntf, hostNameProp);
+
+ return value.get<std::string>();
+}
+
} // namespace dcmi
ipmi_ret_t getPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
@@ -483,6 +494,115 @@
}
}
+ipmi_ret_t getMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ auto requestData = reinterpret_cast<const dcmi::GetMgmntCtrlIdStrRequest *>
+ (request);
+ auto responseData = reinterpret_cast<dcmi::GetMgmntCtrlIdStrResponse *>
+ (response);
+ std::string hostName;
+
+ *data_len = 0;
+
+ if (requestData->groupID != dcmi::groupExtId ||
+ requestData->bytes > dcmi::maxBytes ||
+ requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen)
+ {
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ try
+ {
+ hostName = dcmi::getHostName();
+ }
+ catch (InternalFailure& e)
+ {
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ if (requestData->offset > hostName.length())
+ {
+ return IPMI_CC_PARM_OUT_OF_RANGE;
+ }
+ auto responseStr = hostName.substr(requestData->offset, requestData->bytes);
+ auto responseStrLen = std::min(static_cast<std::size_t>(requestData->bytes),
+ responseStr.length() + 1);
+ responseData->groupID = dcmi::groupExtId;
+ responseData->strLen = hostName.length();
+ std::copy(begin(responseStr), end(responseStr), responseData->data);
+
+ *data_len = sizeof(*responseData) + responseStrLen;
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t setMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ static std::array<char, dcmi::maxCtrlIdStrLen + 1> newCtrlIdStr;
+
+ auto requestData = reinterpret_cast<const dcmi::SetMgmntCtrlIdStrRequest *>
+ (request);
+ auto responseData = reinterpret_cast<dcmi::SetMgmntCtrlIdStrResponse *>
+ (response);
+
+ *data_len = 0;
+
+ if (requestData->groupID != dcmi::groupExtId ||
+ requestData->bytes > dcmi::maxBytes ||
+ requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen + 1 ||
+ (requestData->offset + requestData->bytes == dcmi::maxCtrlIdStrLen + 1 &&
+ requestData->data[requestData->bytes - 1] != '\0'))
+ {
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ try
+ {
+ /* if there is no old value and offset is not 0 */
+ if (newCtrlIdStr[0] == '\0' && requestData->offset != 0)
+ {
+ /* read old ctrlIdStr */
+ auto hostName = dcmi::getHostName();
+ hostName.resize(dcmi::maxCtrlIdStrLen);
+ std::copy(begin(hostName), end(hostName), begin(newCtrlIdStr));
+ newCtrlIdStr[hostName.length()] = '\0';
+ }
+
+ /* replace part of string and mark byte after the last as \0 */
+ auto restStrIter = std::copy_n(requestData->data,
+ requestData->bytes, begin(newCtrlIdStr) + requestData->offset);
+ /* if the last written byte is not 64th - add '\0' */
+ if (requestData->offset + requestData->bytes <= dcmi::maxCtrlIdStrLen)
+ {
+ *restStrIter = '\0';
+ }
+
+ /* if input data contains '\0' whole string is sent - update hostname */
+ auto it = std::find(requestData->data,
+ requestData->data + requestData->bytes, '\0');
+ if (it != requestData->data + requestData->bytes)
+ {
+ sdbusplus::bus::bus bus{ ipmid_get_sd_bus_connection() };
+ ipmi::setDbusProperty(bus, dcmi::networkServiceName,
+ dcmi::networkConfigObj, dcmi::networkConfigIntf,
+ dcmi::hostNameProp, std::string(newCtrlIdStr.data()));
+ }
+ }
+ catch (InternalFailure& e)
+ {
+ *data_len = 0;
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ responseData->groupID = dcmi::groupExtId;
+ responseData->offset = requestData->offset + requestData->bytes;
+ *data_len = sizeof(*responseData);
+ return IPMI_CC_OK;
+}
+
void register_netfn_dcmi_functions()
{
// <Get Power Limit>
@@ -519,6 +639,20 @@
ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_ASSET_TAG,
NULL, setAssetTag, PRIVILEGE_OPERATOR);
+
+ // <Get Managment Controller Identifier String>
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
+ NETFUN_GRPEXT, dcmi::Commands::GET_MGMNT_CTRL_ID_STR);
+
+ ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_MGMNT_CTRL_ID_STR,
+ NULL, getMgmntCtrlIdStr, PRIVILEGE_USER);
+
+ // <Set Management Controller Identifier String>
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
+ NETFUN_GRPEXT, dcmi::Commands::SET_MGMNT_CTRL_ID_STR);
+ ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_MGMNT_CTRL_ID_STR,
+ NULL, setMgmntCtrlIdStr, PRIVILEGE_ADMIN);
+
return;
}
// 956379
diff --git a/dcmihandler.hpp b/dcmihandler.hpp
index 212e9ac..91707f3 100644
--- a/dcmihandler.hpp
+++ b/dcmihandler.hpp
@@ -17,13 +17,20 @@
APPLY_POWER_LIMIT = 0x05,
GET_ASSET_TAG = 0x06,
SET_ASSET_TAG = 0x08,
+ GET_MGMNT_CTRL_ID_STR = 0x09,
+ SET_MGMNT_CTRL_ID_STR = 0x0A,
};
-
static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
static constexpr auto assetTagIntf =
"xyz.openbmc_project.Inventory.Decorator.AssetTag";
static constexpr auto assetTagProp = "AssetTag";
+static constexpr auto networkServiceName = "xyz.openbmc_project.Network";
+static constexpr auto networkConfigObj =
+ "/xyz/openbmc_project/network/config";
+static constexpr auto networkConfigIntf =
+ "xyz.openbmc_project.Network.SystemConfiguration";
+static constexpr auto hostNameProp = "HostName";
namespace assettag
{
@@ -40,6 +47,7 @@
static constexpr auto assetTagMaxOffset = 62;
static constexpr auto assetTagMaxSize = 63;
static constexpr auto maxBytes = 16;
+static constexpr size_t maxCtrlIdStrLen = 63;
/** @struct GetAssetTagRequest
*
@@ -206,6 +214,50 @@
uint8_t groupID; //!< Group extension identification.
} __attribute__((packed));
+/** @struct GetMgmntCtrlIdStrRequest
+ *
+ * DCMI payload for Get Management Controller Identifier String cmd request.
+ */
+struct GetMgmntCtrlIdStrRequest
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint8_t offset; //!< Offset to read.
+ uint8_t bytes; //!< Number of bytes to read.
+} __attribute__((packed));
+
+/** @struct GetMgmntCtrlIdStrResponse
+ *
+ * DCMI payload for Get Management Controller Identifier String cmd response.
+ */
+struct GetMgmntCtrlIdStrResponse
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint8_t strLen; //!< ID string length.
+ char data[]; //!< ID string
+} __attribute__((packed));
+
+/** @struct SetMgmntCtrlIdStrRequest
+ *
+ * DCMI payload for Set Management Controller Identifier String cmd request.
+ */
+struct SetMgmntCtrlIdStrRequest
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint8_t offset; //!< Offset to write.
+ uint8_t bytes; //!< Number of bytes to read.
+ char data[]; //!< ID string
+} __attribute__((packed));
+
+/** @struct GetMgmntCtrlIdStrResponse
+ *
+ * DCMI payload for Get Management Controller Identifier String cmd response.
+ */
+struct SetMgmntCtrlIdStrResponse
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint8_t offset; //!< Last Offset Written.
+} __attribute__((packed));
+
} // namespace dcmi
#endif