diff options
author | Tom Joseph <tomjoseph@in.ibm.com> | 2017-06-30 19:09:47 +0530 |
---|---|---|
committer | Patrick Williams <patrick@stwcx.xyz> | 2017-07-19 19:54:41 +0000 |
commit | a495339f39ace4f729f31f40e837f8d5b76732cb (patch) | |
tree | fe0d9dbeaee5b6ed80c7459abd4c24da44af5c4b | |
parent | 6f7deaa034b1cfd7640b1c21616c6807900d5609 (diff) | |
download | phosphor-host-ipmid-a495339f39ace4f729f31f40e837f8d5b76732cb.tar.gz phosphor-host-ipmid-a495339f39ace4f729f31f40e837f8d5b76732cb.zip |
Add Get SEL entry command
Change-Id: I09983a127c7c2817a0ebb6d64ffb2a9585dcd235
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
-rw-r--r-- | selutility.hpp | 17 | ||||
-rw-r--r-- | storagehandler.cpp | 120 | ||||
-rw-r--r-- | storagehandler.h | 1 |
3 files changed, 138 insertions, 0 deletions
diff --git a/selutility.hpp b/selutility.hpp index 9c253bd..ddf003a 100644 --- a/selutility.hpp +++ b/selutility.hpp @@ -41,6 +41,23 @@ struct GetSELInfoResponse uint8_t operationSupport; //!< Operation support. } __attribute__((packed)); +static constexpr auto firstEntry = 0x0000; +static constexpr auto lastEntry = 0xFFFF; +static constexpr auto entireRecord = 0xFF; +static constexpr auto selRecordSize = 16; + +/** @struct GetSELEntryRequest + * + * IPMI payload for Get SEL Entry command request. + */ +struct GetSELEntryRequest +{ + uint16_t reservationID; //!< Reservation ID. + uint16_t selRecordID; //!< SEL Record ID. + uint8_t offset; //!< Offset into record. + uint8_t readLength; //!< Bytes to read. +} __attribute__((packed)); + /** @struct GetSELEntryResponse * * IPMI payload for Get SEL Entry command response. diff --git a/storagehandler.cpp b/storagehandler.cpp index bbcb441..66db77b 100644 --- a/storagehandler.cpp +++ b/storagehandler.cpp @@ -8,6 +8,7 @@ #include "storagehandler.h" #include "storageaddsel.h" #include "host-ipmid/ipmid-api.h" +#include <experimental/filesystem> #include <phosphor-logging/log.hpp> #include <sdbusplus/server.hpp> #include "xyz/openbmc_project/Common/error.hpp" @@ -94,6 +95,120 @@ ipmi_ret_t getSELInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return IPMI_CC_OK; } +ipmi_ret_t getSELEntry(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 ipmi::sel::GetSELEntryRequest*> + (request); + + if (requestData->reservationID != 0) + { + if (g_sel_reserve != requestData->reservationID) + { + *data_len = 0; + return IPMI_CC_INVALID_RESERVATION_ID; + } + } + + if (cache::paths.empty()) + { + *data_len = 0; + return IPMI_CC_SENSOR_INVALID; + } + + ipmi::sel::ObjectPaths::const_iterator iter; + + // Check for the requested SEL Entry. + if (requestData->selRecordID == ipmi::sel::firstEntry) + { + iter = cache::paths.begin(); + } + else if (requestData->selRecordID == ipmi::sel::lastEntry) + { + iter = cache::paths.end(); + } + else + { + std::string objPath = std::string(ipmi::sel::logBasePath) + "/" + + std::to_string(requestData->selRecordID); + + iter = std::find(cache::paths.begin(), cache::paths.end(), objPath); + if (iter == cache::paths.end()) + { + *data_len = 0; + return IPMI_CC_SENSOR_INVALID; + } + } + + ipmi::sel::GetSELEntryResponse record {}; + + // Convert the log entry into SEL record. + try + { + record = ipmi::sel::convertLogEntrytoSEL(*iter); + } + catch (InternalFailure& e) + { + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + catch (const std::runtime_error& e) + { + log<level::ERR>(e.what()); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + + + // Identify the next SEL record ID + if(iter != cache::paths.end()) + { + ++iter; + if (iter == cache::paths.end()) + { + record.nextRecordID = ipmi::sel::lastEntry; + } + else + { + namespace fs = std::experimental::filesystem; + fs::path path(*iter); + record.nextRecordID = static_cast<uint16_t> + (std::stoul(std::string(path.filename().c_str()))); + } + } + else + { + record.nextRecordID = ipmi::sel::lastEntry; + } + + if (requestData->readLength == ipmi::sel::entireRecord) + { + memcpy(response, &record, sizeof(record)); + *data_len = sizeof(record); + } + else + { + if (requestData->offset >= ipmi::sel::selRecordSize || + requestData->readLength > ipmi::sel::selRecordSize) + { + *data_len = 0; + return IPMI_CC_INVALID_FIELD_REQUEST; + } + + auto diff = ipmi::sel::selRecordSize - requestData->offset; + auto readLength = std::min(diff, + static_cast<int>(requestData->readLength)); + + memcpy(response, &record.nextRecordID, sizeof(record.nextRecordID)); + memcpy(static_cast<uint8_t*>(response) + sizeof(record.nextRecordID), + &record.recordID + requestData->offset, readLength); + *data_len = sizeof(record.nextRecordID) + readLength; + } + + return IPMI_CC_OK; +} + ipmi_ret_t ipmi_storage_get_sel_time(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) @@ -300,6 +415,11 @@ void register_netfn_storage_functions() ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_RESERVE_SEL, NULL, ipmi_storage_reserve_sel, PRIVILEGE_USER); + // <Get SEL Entry> + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_GET_SEL_ENTRY); + ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_ENTRY, NULL, getSELEntry, + PRIVILEGE_USER); + // <Add SEL Entry> printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_ADD_SEL); ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_ADD_SEL, NULL, ipmi_storage_add_sel, diff --git a/storagehandler.h b/storagehandler.h index 174da06..2bfc172 100644 --- a/storagehandler.h +++ b/storagehandler.h @@ -7,6 +7,7 @@ enum ipmi_netfn_storage_cmds // Get capability bits IPMI_CMD_GET_SEL_INFO = 0x40, IPMI_CMD_RESERVE_SEL = 0x42, + IPMI_CMD_GET_SEL_ENTRY = 0x43, IPMI_CMD_ADD_SEL = 0x44, IPMI_CMD_GET_SEL_TIME = 0x48, IPMI_CMD_SET_SEL_TIME = 0x49, |