diff options
Diffstat (limited to 'storagehandler.cpp')
-rw-r--r-- | storagehandler.cpp | 577 |
1 files changed, 263 insertions, 314 deletions
diff --git a/storagehandler.cpp b/storagehandler.cpp index 18f1357..5b9726a 100644 --- a/storagehandler.cpp +++ b/storagehandler.cpp @@ -19,17 +19,24 @@ #include <ipmid/utils.hpp> #include <phosphor-logging/elog-errors.hpp> #include <phosphor-logging/log.hpp> -#include <sdbusplus/message/types.hpp> #include <sdbusplus/server.hpp> #include <string> +#include <variant> #include <xyz/openbmc_project/Common/error.hpp> void register_netfn_storage_functions() __attribute__((constructor)); unsigned int g_sel_time = 0xFFFFFFFF; -extern const ipmi::sensor::IdInfoMap sensors; -extern const FruMap frus; +namespace ipmi +{ +namespace sensor +{ +extern const IdInfoMap sensors; +} // namespace sensor +} // namespace ipmi +extern const FruMap frus; +constexpr uint8_t eventDataSize = 3; namespace { constexpr auto TIME_INTERFACE = "xyz.openbmc_project.Time.EpochTime"; @@ -37,13 +44,6 @@ constexpr auto HOST_TIME_PATH = "/xyz/openbmc_project/time/host"; constexpr auto DBUS_PROPERTIES = "org.freedesktop.DBus.Properties"; constexpr auto PROPERTY_ELAPSED = "Elapsed"; -const char* getTimeString(const uint64_t& usecSinceEpoch) -{ - using namespace std::chrono; - system_clock::time_point tp{microseconds(usecSinceEpoch)}; - auto t = system_clock::to_time_t(tp); - return std::ctime(&t); -} } // namespace namespace cache @@ -62,8 +62,6 @@ ipmi::sel::ObjectPaths paths; } // namespace cache -namespace variant_ns = sdbusplus::message::variant_ns; - using InternalFailure = sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; using namespace phosphor::logging; @@ -78,36 +76,34 @@ enum class AccessMode 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, - ipmi_data_len_t data_len, - ipmi_context_t context) -{ - // Status code. - ipmi_ret_t rc = IPMI_CC_INVALID; - *data_len = 0; - return rc; -} +/** @brief implements the get SEL Info command + * @returns IPMI completion code plus response data + * - selVersion - SEL revision + * - entries - Number of log entries in SEL. + * - freeSpace - Free Space in bytes. + * - addTimeStamp - Most recent addition timestamp + * - eraseTimeStamp - Most recent erase timestamp + * - operationSupport - Reserve & Delete SEL operations supported + */ -ipmi_ret_t getSELInfo(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) +ipmi::RspType<uint8_t, // SEL revision. + uint16_t, // number of log entries in SEL. + uint16_t, // free Space in bytes. + uint32_t, // most recent addition timestamp + uint32_t, // most recent erase timestamp. + + bool, // SEL allocation info supported + bool, // reserve SEL supported + bool, // partial Add SEL Entry supported + bool, // delete SEL supported + uint3_t, // reserved + bool // overflow flag + > + ipmiStorageGetSelInfo() { - if (*data_len != 0) - { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; - } - - std::vector<uint8_t> outPayload(sizeof(ipmi::sel::GetSELInfoResponse)); - auto responseData = - reinterpret_cast<ipmi::sel::GetSELInfoResponse*>(outPayload.data()); - - responseData->selVersion = ipmi::sel::selVersion; - // Last erase timestamp is not available from log manager. - responseData->eraseTimeStamp = ipmi::sel::invalidTimeStamp; - responseData->operationSupport = ipmi::sel::operationSupport; + uint16_t entries = 0; + // Most recent addition timestamp. + uint32_t addTimeStamp = ipmi::sel::invalidTimeStamp; try { @@ -121,16 +117,13 @@ ipmi_ret_t getSELInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, // as 0. } - responseData->entries = 0; - responseData->addTimeStamp = ipmi::sel::invalidTimeStamp; - if (!cache::paths.empty()) { - responseData->entries = static_cast<uint16_t>(cache::paths.size()); + entries = static_cast<uint16_t>(cache::paths.size()); try { - responseData->addTimeStamp = static_cast<uint32_t>( + addTimeStamp = static_cast<uint32_t>( (ipmi::sel::getEntryTimeStamp(cache::paths.back()).count())); } catch (InternalFailure& e) @@ -142,10 +135,18 @@ ipmi_ret_t getSELInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, } } - std::memcpy(response, outPayload.data(), outPayload.size()); - *data_len = outPayload.size(); + constexpr uint8_t selVersion = ipmi::sel::selVersion; + constexpr uint16_t freeSpace = 0xFFFF; + constexpr uint32_t eraseTimeStamp = ipmi::sel::invalidTimeStamp; + constexpr uint3_t reserved{0}; - return IPMI_CC_OK; + return ipmi::responseSuccess( + selVersion, entries, freeSpace, addTimeStamp, eraseTimeStamp, + ipmi::sel::operationSupport::getSelAllocationInfo, + ipmi::sel::operationSupport::reserveSel, + ipmi::sel::operationSupport::partialAddSelEntry, + ipmi::sel::operationSupport::deleteSel, reserved, + ipmi::sel::operationSupport::overflow); } ipmi_ret_t getSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd, @@ -269,24 +270,24 @@ ipmi_ret_t getSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return IPMI_CC_OK; } -ipmi_ret_t deleteSELEntry(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) +/** @brief implements the delete SEL entry command + * @request + * - reservationID; // reservation ID. + * - selRecordID; // SEL record ID. + * + * @returns ipmi completion code plus response data + * - Record ID of the deleted record + */ +ipmi::RspType<uint16_t // deleted record ID + > + deleteSELEntry(uint16_t reservationID, uint16_t selRecordID) { - if (*data_len != sizeof(ipmi::sel::DeleteSELEntryRequest)) - { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; - } namespace fs = std::filesystem; - auto requestData = - reinterpret_cast<const ipmi::sel::DeleteSELEntryRequest*>(request); - if (!checkSELReservation(requestData->reservationID)) + if (!checkSELReservation(reservationID)) { - *data_len = 0; - return IPMI_CC_INVALID_RESERVATION_ID; + return ipmi::responseInvalidReservationId(); } // Per the IPMI spec, need to cancel the reservation when a SEL entry is @@ -301,27 +302,25 @@ ipmi_ret_t deleteSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd, { // readLoggingObjectPaths will throw exception if there are no error // log entries. - *data_len = 0; - return IPMI_CC_SENSOR_INVALID; + return ipmi::responseSensorInvalid(); } if (cache::paths.empty()) { - *data_len = 0; - return IPMI_CC_SENSOR_INVALID; + return ipmi::responseSensorInvalid(); } ipmi::sel::ObjectPaths::const_iterator iter; uint16_t delRecordID = 0; - if (requestData->selRecordID == ipmi::sel::firstEntry) + if (selRecordID == ipmi::sel::firstEntry) { iter = cache::paths.begin(); fs::path path(*iter); delRecordID = static_cast<uint16_t>( std::stoul(std::string(path.filename().c_str()))); } - else if (requestData->selRecordID == ipmi::sel::lastEntry) + else if (selRecordID == ipmi::sel::lastEntry) { iter = cache::paths.end(); fs::path path(*iter); @@ -331,15 +330,14 @@ ipmi_ret_t deleteSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd, else { std::string objPath = std::string(ipmi::sel::logBasePath) + "/" + - std::to_string(requestData->selRecordID); + std::to_string(selRecordID); iter = std::find(cache::paths.begin(), cache::paths.end(), objPath); if (iter == cache::paths.end()) { - *data_len = 0; - return IPMI_CC_SENSOR_INVALID; + return ipmi::responseSensorInvalid(); } - delRecordID = requestData->selRecordID; + delRecordID = selRecordID; } sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; @@ -352,8 +350,7 @@ ipmi_ret_t deleteSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd, catch (const std::runtime_error& e) { log<level::ERR>(e.what()); - *data_len = 0; - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } auto methodCall = bus.new_method_call(service.c_str(), (*iter).c_str(), @@ -361,55 +358,49 @@ ipmi_ret_t deleteSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd, auto reply = bus.call(methodCall); if (reply.is_method_error()) { - *data_len = 0; - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } // Invalidate the cache of dbus entry objects. cache::paths.clear(); - std::memcpy(response, &delRecordID, sizeof(delRecordID)); - *data_len = sizeof(delRecordID); - return IPMI_CC_OK; + return ipmi::responseSuccess(delRecordID); } -ipmi_ret_t clearSEL(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) -{ - if (*data_len != sizeof(ipmi::sel::ClearSELRequest)) - { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; - } - - auto requestData = - reinterpret_cast<const ipmi::sel::ClearSELRequest*>(request); +/** @brief implements the Clear SEL command + * @request + * - reservationID // Reservation ID. + * - clr // char array { 'C'(0x43h), 'L'(0x4Ch), 'R'(0x52h) } + * - eraseOperation; // requested operation. + * + * @returns ipmi completion code plus response data + * - erase status + */ - if (!checkSELReservation(requestData->reservationID)) +ipmi::RspType<uint8_t // erase status + > + clearSEL(uint16_t reservationID, const std::array<char, 3>& clr, + uint8_t eraseOperation) +{ + static constexpr std::array<char, 3> clrOk = {'C', 'L', 'R'}; + if (clr != clrOk) { - *data_len = 0; - return IPMI_CC_INVALID_RESERVATION_ID; + return ipmi::responseInvalidFieldRequest(); } - if (requestData->charC != 'C' || requestData->charL != 'L' || - requestData->charR != 'R') + if (!checkSELReservation(reservationID)) { - *data_len = 0; - return IPMI_CC_INVALID_FIELD_REQUEST; + return ipmi::responseInvalidReservationId(); } - uint8_t eraseProgress = ipmi::sel::eraseComplete; - /* * Erasure status cannot be fetched from DBUS, so always return erasure * status as `erase completed`. */ - if (requestData->eraseOperation == ipmi::sel::getEraseStatus) + if (eraseOperation == ipmi::sel::getEraseStatus) { - std::memcpy(response, &eraseProgress, sizeof(eraseProgress)); - *data_len = sizeof(eraseProgress); - return IPMI_CC_OK; + return ipmi::responseSuccess( + static_cast<uint8_t>(ipmi::sel::eraseComplete)); } // Per the IPMI spec, need to cancel any reservation when the SEL is cleared @@ -431,24 +422,21 @@ ipmi_ret_t clearSEL(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, auto reply = bus.call(mapperCall); if (reply.is_method_error()) { - std::memcpy(response, &eraseProgress, sizeof(eraseProgress)); - *data_len = sizeof(eraseProgress); - return IPMI_CC_OK; + return ipmi::responseSuccess( + static_cast<uint8_t>(ipmi::sel::eraseComplete)); } reply.read(objectPaths); if (objectPaths.empty()) { - std::memcpy(response, &eraseProgress, sizeof(eraseProgress)); - *data_len = sizeof(eraseProgress); - return IPMI_CC_OK; + return ipmi::responseSuccess( + static_cast<uint8_t>(ipmi::sel::eraseComplete)); } } catch (const sdbusplus::exception::SdBusError& e) { - std::memcpy(response, &eraseProgress, sizeof(eraseProgress)); - *data_len = sizeof(eraseProgress); - return IPMI_CC_OK; + return ipmi::responseSuccess( + static_cast<uint8_t>(ipmi::sel::eraseComplete)); } std::string service; @@ -461,8 +449,7 @@ ipmi_ret_t clearSEL(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, catch (const std::runtime_error& e) { log<level::ERR>(e.what()); - *data_len = 0; - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } for (const auto& iter : objectPaths) @@ -473,40 +460,32 @@ ipmi_ret_t clearSEL(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, auto reply = bus.call(methodCall); if (reply.is_method_error()) { - *data_len = 0; - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } } // Invalidate the cache of dbus entry objects. cache::paths.clear(); - std::memcpy(response, &eraseProgress, sizeof(eraseProgress)); - *data_len = sizeof(eraseProgress); - return IPMI_CC_OK; + return ipmi::responseSuccess( + static_cast<uint8_t>(ipmi::sel::eraseComplete)); } -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) +/** @brief implements the get SEL time command + * @returns IPMI completion code plus response data + * -current time + */ +ipmi::RspType<uint32_t> // current time + ipmiStorageGetSelTime() { - if (*data_len != 0) - { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; - } - using namespace std::chrono; uint64_t host_time_usec = 0; - uint32_t resp = 0; std::stringstream hostTime; try { sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; auto service = ipmi::getService(bus, TIME_INTERFACE, HOST_TIME_PATH); - sdbusplus::message::variant<uint64_t> value; + std::variant<uint64_t> value; // Get host time auto method = bus.new_method_call(service.c_str(), HOST_TIME_PATH, @@ -519,64 +498,48 @@ ipmi_ret_t ipmi_storage_get_sel_time(ipmi_netfn_t netfn, ipmi_cmd_t cmd, log<level::ERR>("Error getting time", entry("SERVICE=%s", service.c_str()), entry("PATH=%s", HOST_TIME_PATH)); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } reply.read(value); - host_time_usec = variant_ns::get<uint64_t>(value); + host_time_usec = std::get<uint64_t>(value); } catch (InternalFailure& e) { log<level::ERR>(e.what()); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } - catch (const std::runtime_error& e) + catch (const std::exception& e) { log<level::ERR>(e.what()); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } - hostTime << "Host time:" << getTimeString(host_time_usec); + hostTime << "Host time:" + << duration_cast<seconds>(microseconds(host_time_usec)).count(); log<level::DEBUG>(hostTime.str().c_str()); // Time is really long int but IPMI wants just uint32. This works okay until // the number of seconds since 1970 overflows uint32 size.. Still a whole // lot of time here to even think about that. - resp = duration_cast<seconds>(microseconds(host_time_usec)).count(); - resp = htole32(resp); - - // From the IPMI Spec 2.0, response should be a 32-bit value - *data_len = sizeof(resp); - - // Pack the actual response - std::memcpy(response, &resp, *data_len); - - return IPMI_CC_OK; + return ipmi::responseSuccess( + duration_cast<seconds>(microseconds(host_time_usec)).count()); } -ipmi_ret_t ipmi_storage_set_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) +/** @brief implements the set SEL time command + * @param selDeviceTime - epoch time + * -local time as the number of seconds from 00:00:00, January 1, 1970 + * @returns IPMI completion code + */ +ipmi::RspType<> ipmiStorageSetSelTime(uint32_t selDeviceTime) { - if (*data_len != sizeof(uint32_t)) - { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; - } using namespace std::chrono; - ipmi_ret_t rc = IPMI_CC_OK; - uint32_t secs = *static_cast<uint32_t*>(request); - *data_len = 0; - - secs = le32toh(secs); - microseconds usec{seconds(secs)}; + microseconds usec{seconds(selDeviceTime)}; try { sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; auto service = ipmi::getService(bus, TIME_INTERFACE, HOST_TIME_PATH); - sdbusplus::message::variant<uint64_t> value{usec.count()}; + std::variant<uint64_t> value{usec.count()}; // Set host time auto method = bus.new_method_call(service.c_str(), HOST_TIME_PATH, @@ -589,257 +552,243 @@ ipmi_ret_t ipmi_storage_set_sel_time(ipmi_netfn_t netfn, ipmi_cmd_t cmd, log<level::ERR>("Error setting time", entry("SERVICE=%s", service.c_str()), entry("PATH=%s", HOST_TIME_PATH)); - rc = IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } } catch (InternalFailure& e) { log<level::ERR>(e.what()); - rc = IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } - catch (const std::runtime_error& e) + catch (const std::exception& e) { log<level::ERR>(e.what()); - rc = IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } - return rc; + return ipmi::responseSuccess(); } -ipmi_ret_t ipmi_storage_reserve_sel(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) +/** @brief implements the reserve SEL command + * @returns IPMI completion code plus response data + * - SEL reservation ID. + */ +ipmi::RspType<uint16_t> ipmiStorageReserveSel() { - if (*data_len != 0) - { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; - } - - ipmi_ret_t rc = IPMI_CC_OK; - unsigned short selResID = reserveSel(); - - *data_len = sizeof(selResID); - - // Pack the actual response - std::memcpy(response, &selResID, *data_len); - - return rc; + return ipmi::responseSuccess(reserveSel()); } -ipmi_ret_t ipmi_storage_add_sel(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) +/** @brief implements the Add SEL entry command + * @request + * + * - recordID ID used for SEL Record access + * - recordType Record Type + * - timeStamp Time when event was logged. LS byte first + * - generatorID software ID if event was generated from + * system software + * - evmRev event message format version + * - sensorType sensor type code for service that generated + * the event + * - sensorNumber number of sensors that generated the event + * - eventDir event dir + * - eventData event data field contents + * + * @returns ipmi completion code plus response data + * - RecordID of the Added SEL entry + */ +ipmi::RspType<uint16_t // recordID of the Added SEL entry + > + ipmiStorageAddSEL(uint16_t recordID, uint8_t recordType, uint32_t timeStamp, + uint16_t generatorID, uint8_t evmRev, uint8_t sensorType, + uint8_t sensorNumber, uint8_t eventDir, + std::array<uint8_t, eventDataSize> eventData) { - if (*data_len != sizeof(ipmi_add_sel_request_t)) - { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; - } - - ipmi_ret_t rc = IPMI_CC_OK; - ipmi_add_sel_request_t* p = (ipmi_add_sel_request_t*)request; - uint16_t recordid; - // Per the IPMI spec, need to cancel the reservation when a SEL entry is // added cancelSELReservation(); - - recordid = ((uint16_t)p->eventdata[1] << 8) | p->eventdata[2]; - - *data_len = sizeof(recordid); - - // Pack the actual response - std::memcpy(response, &p->eventdata[1], 2); - // Hostboot sends SEL with OEM record type 0xDE to indicate that there is // a maintenance procedure associated with eSEL record. static constexpr auto procedureType = 0xDE; - if (p->recordtype == procedureType) + if (recordType == procedureType) { // In the OEM record type 0xDE, byte 11 in the SEL record indicate the // procedure number. - createProcedureLogEntry(p->sensortype); + createProcedureLogEntry(sensorType); } - return rc; + return ipmi::responseSuccess(recordID); } -// Read FRU info area -ipmi_ret_t ipmi_storage_get_fru_inv_area_info( - 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) +/** @brief implements the get FRU Inventory Area Info command + * + * @returns IPMI completion code plus response data + * - FRU Inventory area size in bytes, + * - access bit + **/ +ipmi::RspType<uint16_t, // FRU Inventory area size in bytes, + uint8_t // access size (bytes / words) + > + ipmiStorageGetFruInvAreaInfo(uint8_t fruID) { - ipmi_ret_t rc = IPMI_CC_OK; - const FruInvenAreaInfoRequest* reqptr = - reinterpret_cast<const FruInvenAreaInfoRequest*>(request); - auto iter = frus.find(reqptr->fruID); + auto iter = frus.find(fruID); if (iter == frus.end()) { - *data_len = 0; - return IPMI_CC_SENSOR_INVALID; + return ipmi::responseSensorInvalid(); } 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 - std::memcpy(response, &resp, *data_len); + return ipmi::responseSuccess( + static_cast<uint16_t>(getFruAreaData(fruID).size()), + static_cast<uint8_t>(AccessMode::bytes)); } catch (const InternalFailure& e) { - rc = IPMI_CC_UNSPECIFIED_ERROR; - *data_len = 0; log<level::ERR>(e.what()); + return ipmi::responseUnspecifiedError(); } - return rc; } -// Read FRU data -ipmi_ret_t ipmi_storage_read_fru_data(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) +/**@brief implements the Read FRU Data command + * @param fruDeviceId - FRU device ID. FFh = reserved + * @param offset - FRU inventory offset to read + * @param readCount - count to read + * + * @return IPMI completion code plus response data + * - returnCount - response data count. + * - data - response data + */ +ipmi::RspType<uint8_t, // count returned + std::vector<uint8_t>> // FRU data + ipmiStorageReadFruData(uint8_t fruDeviceId, uint16_t offset, + uint8_t readCount) { - ipmi_ret_t rc = IPMI_CC_OK; - const ReadFruDataRequest* reqptr = - reinterpret_cast<const ReadFruDataRequest*>(request); - auto resptr = reinterpret_cast<ReadFruDataResponse*>(response); + if (fruDeviceId == 0xFF) + { + return ipmi::responseInvalidFieldRequest(); + } - auto iter = frus.find(reqptr->fruID); + auto iter = frus.find(fruDeviceId); if (iter == frus.end()) { - *data_len = 0; - return IPMI_CC_SENSOR_INVALID; + return ipmi::responseSensorInvalid(); } - auto offset = - static_cast<uint16_t>(reqptr->offsetMS << 8 | reqptr->offsetLS); try { - const auto& fruArea = getFruAreaData(reqptr->fruID); + const auto& fruArea = getFruAreaData(fruDeviceId); auto size = fruArea.size(); if (offset >= size) { - return IPMI_CC_PARM_OUT_OF_RANGE; + return ipmi::responseParmOutOfRange(); } // Write the count of response data. - if ((offset + reqptr->count) <= size) + uint8_t returnCount; + if ((offset + readCount) <= size) { - resptr->count = reqptr->count; + returnCount = readCount; } else { - resptr->count = size - offset; + returnCount = size - offset; } - std::copy((fruArea.begin() + offset), - (fruArea.begin() + offset + resptr->count), resptr->data); + std::vector<uint8_t> fruData((fruArea.begin() + offset), + (fruArea.begin() + offset + returnCount)); - *data_len = resptr->count + 1; // additional one byte for count + return ipmi::responseSuccess(returnCount, fruData); } catch (const InternalFailure& e) { - rc = IPMI_CC_UNSPECIFIED_ERROR; - *data_len = 0; log<level::ERR>(e.what()); + return ipmi::responseUnspecifiedError(); } - return rc; } -ipmi_ret_t ipmi_get_repository_info(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) +ipmi::RspType<uint8_t, // SDR version + uint16_t, // record count LS first + uint16_t, // free space in bytes, LS first + uint32_t, // addition timestamp LS first + uint32_t, // deletion timestamp LS first + uint8_t> // operation Support + ipmiGetRepositoryInfo() { - constexpr auto sdrVersion = 0x51; - auto responseData = reinterpret_cast<GetRepositoryInfoResponse*>(response); - - std::memset(responseData, 0, sizeof(GetRepositoryInfoResponse)); - responseData->sdrVersion = sdrVersion; + constexpr uint8_t sdrVersion = 0x51; + constexpr uint16_t freeSpace = 0xFFFF; + constexpr uint32_t additionTimestamp = 0x0; + constexpr uint32_t deletionTimestamp = 0x0; + constexpr uint8_t operationSupport = 0; - uint16_t records = frus.size() + sensors.size(); - responseData->recordCountMs = records >> 8; - responseData->recordCountLs = records; + uint16_t records = frus.size() + ipmi::sensor::sensors.size(); - responseData->freeSpace[0] = 0xFF; - responseData->freeSpace[1] = 0xFF; - - *data_len = sizeof(GetRepositoryInfoResponse); - - return IPMI_CC_OK; + return ipmi::responseSuccess(sdrVersion, records, freeSpace, + additionTimestamp, deletionTimestamp, + operationSupport); } void register_netfn_storage_functions() { - // <Wildcard Command> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_WILDCARD, NULL, - ipmi_storage_wildcard, PRIVILEGE_USER); - // <Get SEL Info> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_INFO, NULL, - getSELInfo, PRIVILEGE_USER); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdGetSelInfo, ipmi::Privilege::User, + ipmiStorageGetSelInfo); // <Get SEL Time> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_TIME, NULL, - ipmi_storage_get_sel_time, PRIVILEGE_USER); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdGetSelTime, ipmi::Privilege::User, + ipmiStorageGetSelTime); // <Set SEL Time> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_SET_SEL_TIME, NULL, - ipmi_storage_set_sel_time, PRIVILEGE_OPERATOR); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdSetSelTime, + ipmi::Privilege::Operator, ipmiStorageSetSelTime); // <Reserve SEL> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_RESERVE_SEL, NULL, - ipmi_storage_reserve_sel, PRIVILEGE_USER); - + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdReserveSel, ipmi::Privilege::User, + ipmiStorageReserveSel); // <Get SEL Entry> ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_ENTRY, NULL, getSELEntry, PRIVILEGE_USER); // <Delete SEL Entry> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_DELETE_SEL, NULL, - deleteSELEntry, PRIVILEGE_OPERATOR); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdDeleteSelEntry, + ipmi::Privilege::Operator, deleteSELEntry); // <Add SEL Entry> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_ADD_SEL, NULL, - ipmi_storage_add_sel, PRIVILEGE_OPERATOR); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdAddSelEntry, + ipmi::Privilege::Operator, ipmiStorageAddSEL); + // <Clear SEL> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_CLEAR_SEL, NULL, clearSEL, - PRIVILEGE_OPERATOR); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdClearSel, ipmi::Privilege::Operator, + clearSEL); + // <Get FRU Inventory Area Info> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_FRU_INV_AREA_INFO, NULL, - ipmi_storage_get_fru_inv_area_info, - PRIVILEGE_OPERATOR); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdGetFruInventoryAreaInfo, + ipmi::Privilege::User, ipmiStorageGetFruInvAreaInfo); - // <Add READ FRU Data - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_READ_FRU_DATA, NULL, - ipmi_storage_read_fru_data, PRIVILEGE_OPERATOR); + // <READ FRU Data> + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdReadFruData, + ipmi::Privilege::Operator, ipmiStorageReadFruData); // <Get Repository Info> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_REPOSITORY_INFO, - nullptr, ipmi_get_repository_info, PRIVILEGE_USER); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdGetSdrRepositoryInfo, + ipmi::Privilege::User, ipmiGetRepositoryInfo); // <Reserve SDR Repository> - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_RESERVE_SDR, nullptr, - ipmi_sen_reserve_sdr, PRIVILEGE_USER); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage, + ipmi::storage::cmdReserveSdrRepository, + ipmi::Privilege::User, ipmiSensorReserveSdr); // <Get SDR> ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SDR, nullptr, |