diff options
-rw-r--r-- | selutility.hpp | 17 | ||||
-rw-r--r-- | storagehandler.cpp | 104 | ||||
-rw-r--r-- | storagehandler.h | 1 |
3 files changed, 122 insertions, 0 deletions
diff --git a/selutility.hpp b/selutility.hpp index 50babca..2cae8c3 100644 --- a/selutility.hpp +++ b/selutility.hpp @@ -88,6 +88,23 @@ struct DeleteSELEntryRequest uint16_t selRecordID; //!< SEL Record ID. } __attribute__((packed)); +static constexpr auto initiateErase = 0xAA; +static constexpr auto getEraseStatus = 0x00; +static constexpr auto eraseComplete = 0x01; + +/** @struct ClearSELRequest + * + * IPMI payload for Clear SEL command request. + */ +struct ClearSELRequest +{ + uint16_t reservationID; //!< Reservation ID. + uint8_t charC; //!< Char 'C'(0x43h). + uint8_t charL; //!< Char 'L'(0x4Ch). + uint8_t charR; //!< Char 'R'(0x52h). + uint8_t eraseOperation; //!< Erase operation. +} __attribute__((packed)); + /** @brief Convert logging entry to SEL * * @param[in] objPath - DBUS object path of the logging entry. diff --git a/storagehandler.cpp b/storagehandler.cpp index cd6f10c..5ded63e 100644 --- a/storagehandler.cpp +++ b/storagehandler.cpp @@ -296,6 +296,105 @@ ipmi_ret_t deleteSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return IPMI_CC_OK; } +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) +{ + auto requestData = reinterpret_cast<const ipmi::sel::ClearSELRequest*> + (request); + + if (g_sel_reserve != requestData->reservationID) + { + *data_len = 0; + return IPMI_CC_INVALID_RESERVATION_ID; + } + + if (requestData->charC != 'C' || + requestData->charL != 'L' || + requestData->charR != 'R') + { + *data_len = 0; + return IPMI_CC_INVALID_FIELD_REQUEST; + } + + 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) + { + memcpy(response, &eraseProgress, sizeof(eraseProgress)); + *data_len = sizeof(eraseProgress); + return IPMI_CC_OK; + } + + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + auto depth = 0; + + auto mapperCall = bus.new_method_call(ipmi::sel::mapperBusName, + ipmi::sel::mapperObjPath, + ipmi::sel::mapperIntf, + "GetSubTreePaths"); + mapperCall.append(ipmi::sel::logBasePath); + mapperCall.append(depth); + mapperCall.append(ipmi::sel::ObjectPaths({ipmi::sel::logEntryIntf})); + + auto reply = bus.call(mapperCall); + if (reply.is_method_error()) + { + memcpy(response, &eraseProgress, sizeof(eraseProgress)); + *data_len = sizeof(eraseProgress); + return IPMI_CC_OK; + } + + ipmi::sel::ObjectPaths objectPaths; + reply.read(objectPaths); + if (objectPaths.empty()) + { + memcpy(response, &eraseProgress, sizeof(eraseProgress)); + *data_len = sizeof(eraseProgress); + return IPMI_CC_OK; + } + + std::string service; + + try + { + service = ipmi::getService(bus, + ipmi::sel::logDeleteIntf, + objectPaths.front()); + } + catch (const std::runtime_error& e) + { + log<level::ERR>(e.what()); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + + for (const auto& iter : objectPaths) + { + auto methodCall = bus.new_method_call(service.c_str(), + iter.c_str(), + ipmi::sel::logDeleteIntf, + "Delete"); + + auto reply = bus.call(methodCall); + if (reply.is_method_error()) + { + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + } + + // Invalidate the cache of dbus entry objects. + cache::paths.clear(); + memcpy(response, &eraseProgress, sizeof(eraseProgress)); + *data_len = sizeof(eraseProgress); + 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) @@ -516,6 +615,11 @@ void register_netfn_storage_functions() 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, PRIVILEGE_OPERATOR); + + // <Clear SEL> + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_CLEAR_SEL); + ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_CLEAR_SEL, NULL, clearSEL, + PRIVILEGE_OPERATOR); return; } diff --git a/storagehandler.h b/storagehandler.h index e39d676..9973d14 100644 --- a/storagehandler.h +++ b/storagehandler.h @@ -10,6 +10,7 @@ enum ipmi_netfn_storage_cmds IPMI_CMD_GET_SEL_ENTRY = 0x43, IPMI_CMD_ADD_SEL = 0x44, IPMI_CMD_DELETE_SEL = 0x46, + IPMI_CMD_CLEAR_SEL = 0x47, IPMI_CMD_GET_SEL_TIME = 0x48, IPMI_CMD_SET_SEL_TIME = 0x49, |