diff options
-rw-r--r-- | dcmihandler.cpp | 134 | ||||
-rw-r--r-- | dcmihandler.hpp | 54 |
2 files changed, 187 insertions, 1 deletions
diff --git a/dcmihandler.cpp b/dcmihandler.cpp index 5df6559..806ddd0 100644 --- a/dcmihandler.cpp +++ b/dcmihandler.cpp @@ -207,6 +207,17 @@ void writeAssetTag(const std::string& assetTag) } } +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 setAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd, } } +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 @@ void register_netfn_dcmi_functions() 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 @@ enum Commands 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 groupExtId = 0xDC; 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 @@ struct ApplyPowerLimitResponse 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 |