diff options
-rw-r--r-- | storagehandler.cpp | 67 | ||||
-rw-r--r-- | storagehandler.h | 32 |
2 files changed, 96 insertions, 3 deletions
diff --git a/storagehandler.cpp b/storagehandler.cpp index a1b3f03..36e1bb4 100644 --- a/storagehandler.cpp +++ b/storagehandler.cpp @@ -5,6 +5,7 @@ #include <mapper.h> #include <chrono> #include "selutility.hpp" +#include <algorithm> #include "storagehandler.h" #include "storageaddsel.h" #include "utils.hpp" @@ -13,10 +14,11 @@ #include <phosphor-logging/log.hpp> #include <sdbusplus/server.hpp> #include "xyz/openbmc_project/Common/error.hpp" +#include "read_fru_data.hpp" +#include <phosphor-logging/elog-errors.hpp> void register_netfn_storage_functions() __attribute__((constructor)); - unsigned int g_sel_time = 0xFFFFFFFF; extern unsigned short g_sel_reserve; @@ -42,6 +44,17 @@ namespace cache using InternalFailure = sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; using namespace phosphor::logging; +using namespace ipmi::fru; + +/** + * @enum Device access mode + */ +enum class AccessMode +{ + bytes, ///< Device is accessed by bytes + words ///< Device is accessed by words +}; + ipmi_ret_t ipmi_storage_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, @@ -579,6 +592,29 @@ ipmi_ret_t ipmi_storage_get_fru_inv_area_info( ipmi_context_t context) { ipmi_ret_t rc = IPMI_CC_OK; + const FruInvenAreaInfoRequest* reqptr = + reinterpret_cast<const FruInvenAreaInfoRequest*>(request); + try + { + const auto& fruArea = getFruAreaData(reqptr->fruID); + auto size = static_cast<uint16_t>(fruArea.size()); + FruInvenAreaInfoResponse resp; + resp.sizems = size >> 8; + resp.sizels = size; + resp.access = static_cast<uint8_t>(AccessMode::bytes); + + *data_len = sizeof(resp); + + // Pack the actual response + memcpy(response, &resp, *data_len); + } + catch(const InternalFailure& e) + { + rc = IPMI_CC_UNSPECIFIED_ERROR; + *data_len = 0; + log<level::ERR>(e.what()); + report<InternalFailure>(); + } return rc; } @@ -589,11 +625,36 @@ ipmi_ret_t ipmi_storage_read_fru_data( ipmi_context_t context) { ipmi_ret_t rc = IPMI_CC_OK; + const ReadFruDataRequest* reqptr = + reinterpret_cast<const ReadFruDataRequest*>(request); + auto offset = + static_cast<uint16_t>(reqptr->offsetMS << 8 | reqptr->offsetLS); + try + { + const auto& fruArea = getFruAreaData(reqptr->fruID); + auto size = fruArea.size(); + if ((offset + reqptr->count) > size) + { + log<level::ERR>("Invalid offset and count", + entry("Offset=%d Count=%d SizeOfFruArea=%d", + offset, reqptr->count, size)); + return IPMI_CC_INVALID; + } + std::copy((fruArea.begin() + offset), (fruArea.begin() + reqptr->count), + (static_cast<uint8_t*>(response))); + *data_len = reqptr->count; + } + catch (const InternalFailure& e) + { + rc = IPMI_CC_UNSPECIFIED_ERROR; + *data_len = 0; + log<level::ERR>(e.what()); + report<InternalFailure>(); + } return rc; } - void register_netfn_storage_functions() { // <Wildcard Command> @@ -648,9 +709,9 @@ void register_netfn_storage_functions() // <Add READ FRU Data printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_STORAGE, IPMI_CMD_READ_FRU_DATA); - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_READ_FRU_DATA, NULL, ipmi_storage_read_fru_data, PRIVILEGE_OPERATOR); + return; } diff --git a/storagehandler.h b/storagehandler.h index 7f1b67d..a971f77 100644 --- a/storagehandler.h +++ b/storagehandler.h @@ -30,4 +30,36 @@ struct ipmi_add_sel_request_t { uint8_t eventdir; uint8_t eventdata[3]; }; + +/** + * @struct Read FRU Data command request data + */ +struct ReadFruDataRequest +{ + uint8_t fruID; ///< FRU Device ID. FFh = reserved + uint8_t offsetLS; ///< FRU Inventory Offset to read, LS Byte + uint8_t offsetMS; ///< FRU Inventory Offset ro read, MS Byte + uint8_t count; ///< Count to read +}__attribute__ ((packed)); + +/** + * @struct Get FRU inventory area info command request data + */ +struct FruInvenAreaInfoRequest +{ + uint8_t fruID; ///< FRU Device ID. FFH = reserved. +}__attribute__ ((packed)); + + +/** + * @struct Get FRU inventory area info command response + */ +struct FruInvenAreaInfoResponse +{ + uint8_t completionCode; ///< Completion code + uint8_t sizels; ///< Fru Inventory area size in bytes, LS Byte + uint8_t sizems; ///< Fru Inventory are size in bytes, MS Byte + uint8_t access; ///< 0b Devices is accessed by bytes, 1b - by words +}__attribute__ ((packed)); + #endif |