| /** |
| * Copyright © 2019 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #pragma once |
| |
| #include "i2c_interface.hpp" |
| |
| #include <sdbusplus/bus.hpp> |
| |
| #include <filesystem> |
| #include <memory> |
| #include <string> |
| |
| class TestUpdater; |
| |
| namespace updater |
| { |
| |
| namespace fs = std::filesystem; |
| |
| constexpr auto FW_UPDATE_FAILED_MSG = |
| "xyz.openbmc_project.Power.PowerSupply.Error.FirmwareUpdateFailed"; |
| constexpr auto PSU_FW_FILE_ISSUE_MSG = |
| "xyz.openbmc_project.Power.PowerSupply.Error.FirmwareIssue"; |
| constexpr auto FW_UPDATE_SUCCESS_MSG = |
| "xyz.openbmc_project.Power.PowerSupply.Info.FirmwareUpdateSuccessful"; |
| |
| constexpr auto ERROR_SEVERITY = "xyz.openbmc_project.Logging.Entry.Level.Error"; |
| constexpr auto INFORMATIONAL_SEVERITY = |
| "xyz.openbmc_project.Logging.Entry.Level.Informational"; |
| |
| /** |
| * Update PSU firmware |
| * |
| * @param[in] bus - The sdbusplus DBus bus connection |
| * @param[in] psuInventoryPath - The inventory path of the PSU |
| * @param[in] imageDir - The directory containing the PSU image |
| * |
| * @return true if successful, otherwise false |
| */ |
| bool update(sdbusplus::bus_t& bus, const std::string& psuInventoryPath, |
| const std::string& imageDir); |
| |
| /** |
| * Validate number of present PSUs vs number of required PSUs for this system, |
| * and validate all PSUs have same model before proceeding to Update PSU |
| * firmware |
| * |
| * @param[in] bus - The sdbusplus DBus bus connection |
| * @param[in] psuInventoryPath - The inventory path of the PSU |
| * @param[in] imageDir - The directory containing the PSU image |
| * |
| * @return true if successful, otherwise false |
| */ |
| bool validateAndUpdate(sdbusplus::bus_t& bus, |
| const std::string& psuInventoryPath, |
| const std::string& imageDir); |
| |
| class Updater |
| { |
| public: |
| friend TestUpdater; |
| Updater() = delete; |
| Updater(const Updater&) = delete; |
| Updater& operator=(const Updater&) = delete; |
| Updater(Updater&&) = default; |
| Updater& operator=(Updater&&) = default; |
| |
| /** |
| * @brief Constructor |
| * |
| * @param psuInventoryPath - The PSU inventory path |
| * @param devPath - The PSU device path |
| * @param imageDir - The update image directory |
| */ |
| Updater(const std::string& psuInventoryPath, const std::string& devPath, |
| const std::string& imageDir); |
| |
| /** @brief Destructor */ |
| virtual ~Updater() = default; |
| |
| /** @brief Bind or unbind the driver |
| * |
| * @param doBind - indicate if it's going to bind or unbind the driver |
| */ |
| void bindUnbind(bool doBind); |
| |
| /** @brief Set the PSU inventory present property |
| * |
| * @param present - The present state to set |
| */ |
| void setPresent(bool present); |
| |
| /** @brief Check if it's ready to update the PSU |
| * |
| * @return true if it's ready, otherwise false |
| */ |
| bool isReadyToUpdate(); |
| |
| /** @brief Do the PSU update |
| * |
| * @return 0 if success, otherwise non-zero |
| */ |
| virtual int doUpdate(); |
| |
| /** @brief Create I2C device |
| * |
| * Creates the I2C device based on the device name. |
| * e.g. It opens busId 3, address 0x68 for "3-0068" |
| */ |
| void createI2CDevice(); |
| |
| protected: |
| /** @brief Accessor for PSU inventory path */ |
| const std::string& getPsuInventoryPath() const |
| { |
| return psuInventoryPath; |
| } |
| |
| /** @brief Accessor for device path */ |
| const std::string& getDevPath() const |
| { |
| return devPath; |
| } |
| |
| /** @brief Accessor for device name */ |
| const std::string& getDevName() const |
| { |
| return devName; |
| } |
| |
| /** @brief Accessor for image directory */ |
| const std::string& getImageDir() const |
| { |
| return imageDir; |
| } |
| |
| /** @brief I2C interface accessor */ |
| i2c::I2CInterface* getI2C() |
| { |
| return i2c.get(); |
| } |
| |
| /** |
| * @brief Creates a serviceable Predictive Event Log, |
| * |
| * This method generates an event log with the given error name, severity, |
| * and additional data. It interacts with the OpenBMC logging service to |
| * record faults. |
| * |
| * @param[in] errorName The name of the error to log. |
| * @param[in] severity The severity level of the error. |
| * @param[in] additionalData Additional key-value pairs containing details |
| * about the error. |
| */ |
| void createServiceableEventLog( |
| const std::string& errorName, const std::string& severity, |
| std::map<std::string, std::string>& additionalData); |
| |
| /** |
| * @brief Retrieves additional data related to I2C communication. |
| * |
| * This method collects and returns I2C bus information, including the |
| * bus ID, address, and error number, which are used for reporting |
| * Predictive Error Log. |
| * |
| * @return A map containing I2C-related key-value pairs. |
| */ |
| std::map<std::string, std::string> getI2CAdditionalData(); |
| |
| /** |
| * @brief Call out an I2C-related Predictive Error Log. |
| * |
| * This method creates a serviceable event log related to I2C failures. |
| * It collects additional data about the I2C communication and logs the |
| * failure with appropriate severity. |
| * |
| * @param[in] extraAdditionalData Additional key-value pairs specific to |
| * the error context. |
| * @param[in] exceptionString A string describing the exception that |
| * triggered the error. |
| * @param[in] errorCode Exception error code. |
| */ |
| void callOutI2CEventLog( |
| std::map<std::string, std::string> extraAdditionalData, |
| const std::string& exceptionString = "", const int errorCode = 0); |
| |
| /** |
| * @brief Call out a PSU-related Predictive Error Log. |
| * |
| * This method logs a failure related to PSU firmware updates and additional |
| * diagnostics data to the event log. |
| * |
| * @param[in] extraAdditionalData Additional key-value pairs specific to |
| * the PSU-related error. |
| */ |
| void callOutPsuEventLog( |
| std::map<std::string, std::string> extraAdditionalData); |
| |
| /** |
| * @brief Call out a software-related Predictive Error Log. |
| * |
| * This method logs a failure related to PSU firmware file issues or other |
| * software-related errors. It merges any additional error-specific data |
| * before logging the event. |
| * |
| * @param[in] extraAdditionalData Additional key-value pairs specific to |
| * the software-related error. |
| */ |
| void callOutSWEventLog( |
| std::map<std::string, std::string> extraAdditionalData); |
| |
| /** |
| * @brief Accessor to set logEventLog to true |
| * |
| */ |
| void enableEventLogging() |
| { |
| eventLogState = true; |
| } |
| |
| /** |
| * @brief Accessor to set eventLogState to false |
| * |
| */ |
| void disableEventLogging() |
| { |
| eventLogState = false; |
| } |
| |
| /** |
| * @brief Accessor eventLogState status (enable true, disable false) |
| * |
| * @return true or false |
| */ |
| bool isEventLogEnabled() |
| { |
| return eventLogState; |
| } |
| |
| /** |
| * @brief Accessor to disable eventLoggedThisSession |
| * |
| */ |
| void enableEventLoggedThisSession() |
| { |
| eventLoggedThisSession = true; |
| } |
| |
| /** |
| * @brief Accessor to retieve eventLoggedThisSession status |
| * |
| * @return true or false |
| */ |
| bool isEventLoggedThisSession() |
| { |
| return eventLoggedThisSession; |
| } |
| |
| /** |
| * @brief Call out successful PSU firmware update. |
| * |
| */ |
| void callOutGoodEventLog(); |
| |
| private: |
| /** @brief The sdbusplus DBus bus connection */ |
| sdbusplus::bus_t bus; |
| |
| /** @brief The PSU inventory path */ |
| std::string psuInventoryPath; |
| |
| /** @brief The PSU device path |
| * |
| * Usually it is a device in i2c subsystem, e.g. |
| * /sys/bus/i2c/devices/3-0068 |
| */ |
| std::string devPath; |
| |
| /** @brief The PSU device name |
| * |
| * Usually it is a i2c device name, e.g. |
| * 3-0068 |
| */ |
| std::string devName; |
| |
| /** @brief The PSU image directory */ |
| std::string imageDir; |
| |
| /** @brief The PSU device driver's path |
| * |
| * Usually it is the PSU driver, e.g. |
| * /sys/bus/i2c/drivers/ibm-cffps |
| */ |
| fs::path driverPath; |
| |
| /** @brief The i2c device interface */ |
| std::unique_ptr<i2c::I2CInterface> i2c; |
| |
| /** @brief Event Log flag */ |
| bool eventLogState = false; |
| |
| /** @brief Event logged this session flag, this is to make sure no other |
| * event log can be logged |
| */ |
| bool eventLoggedThisSession = false; |
| }; |
| |
| namespace internal |
| { |
| |
| /** |
| * @brief Factory function to create an Updater instance based on PSU model |
| * number |
| * |
| * @param[in] model - PSU model number |
| * @param[in] psuInventoryPath - PSU inventory path |
| * @param[in] devPath - Device path |
| * @param[in] imageDir - Image directory |
| * |
| * return pointer class based on the device PSU model. |
| */ |
| std::unique_ptr<updater::Updater> getClassInstance( |
| const std::string& model, const std::string& psuInventoryPath, |
| const std::string& devPath, const std::string& imageDir); |
| |
| /** |
| * @brief Retrieve the firmware filename path in the specified directory |
| * |
| * @param[in] directory - Path to FS directory |
| * |
| * @retun filename or null |
| */ |
| const std::string getFWFilenamePath(const std::string& directory); |
| |
| /** |
| * @brief Calculate CRC-8 for a data vector |
| * |
| * @param[in] data - Firmware data block |
| * |
| * @return CRC8 |
| */ |
| uint8_t calculateCRC8(const std::vector<uint8_t>& data); |
| |
| /** |
| * @brief Delay execution in milliseconds |
| * |
| * @param[in] milliseconds - Time in milliseconds |
| */ |
| void delay(const int& milliseconds); |
| |
| /** |
| * @brief Convert a big-endian value to little-endian |
| * |
| * @param[in] bigEndianValue - Uint 32 bit value |
| * |
| * @return vector of little endians. |
| */ |
| std::vector<uint8_t> bigEndianToLittleEndian(const uint32_t bigEndianValue); |
| |
| /** |
| * @brief Validate the existence and size of a firmware file. |
| * |
| * @param[in] fileName - Firmware file name |
| * |
| * @return true for success or false |
| */ |
| bool validateFWFile(const std::string& fileName); |
| |
| /** |
| * @brief Open a firmware file for reading in binary mode. |
| * |
| * @param[in] fileName - Firmware file name |
| * |
| * @return pointer to firmware file stream |
| */ |
| std::unique_ptr<std::ifstream> openFirmwareFile(const std::string& fileName); |
| |
| /** |
| * @brief Read firmware bytes from file. |
| * |
| * @param[in] inputFile - Input file stream |
| * @param[in] numberOfBytesToRead - Number of bytes to read from firmware file. |
| * |
| * @return vector of data read |
| */ |
| std::vector<uint8_t> readFirmwareBytes(std::ifstream& inputFile, |
| const size_t numberOfBytesToRead); |
| |
| } // namespace internal |
| } // namespace updater |