|  | /** | 
|  | * Copyright © 2024 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 "updater.hpp" | 
|  |  | 
|  | namespace aeiUpdater | 
|  | { | 
|  | /** | 
|  | * @class AeiUpdater | 
|  | * @brief A class to handle firmware updates for the AEI PSUs. | 
|  | * | 
|  | * This class provides methods to update firmware by writing ISP keys, | 
|  | * validating firmware files, and performing I2C communications. It includes | 
|  | * functions to manage the update process, including downloading firmware blocks | 
|  | * and verifying the update status. | 
|  | */ | 
|  | class AeiUpdater : public updater::Updater | 
|  | { | 
|  | public: | 
|  | AeiUpdater() = delete; | 
|  | AeiUpdater(const AeiUpdater&) = delete; | 
|  | AeiUpdater(AeiUpdater&&) = delete; | 
|  | AeiUpdater& operator=(const AeiUpdater&) = delete; | 
|  | AeiUpdater& operator=(AeiUpdater&&) = delete; | 
|  | ~AeiUpdater() = default; | 
|  |  | 
|  | /** | 
|  | * @brief Constructor for the AeiUpdater class. | 
|  | * | 
|  | * @param psuInventoryPath The path to the PSU's inventory in the system. | 
|  | * @param devPath The device path for the PSU. | 
|  | * @param imageDir The directory containing the firmware image files. | 
|  | */ | 
|  | AeiUpdater(const std::string& psuInventoryPath, const std::string& devPath, | 
|  | const std::string& imageDir) : | 
|  | Updater(psuInventoryPath, devPath, imageDir) | 
|  | {} | 
|  |  | 
|  | /** | 
|  | * @brief Initiates the firmware update process. | 
|  | * | 
|  | * @return Status code 0 for success or 1 for failure. | 
|  | */ | 
|  | int doUpdate() override; | 
|  |  | 
|  | private: | 
|  | /** | 
|  | * @brief Writes an ISP (In-System Programming) key to initiate the update. | 
|  | * | 
|  | * @return True if successful, false otherwise. | 
|  | */ | 
|  | bool writeIspKey(); | 
|  |  | 
|  | /** | 
|  | * @brief Writes the mode required for ISP to start firmware programming. | 
|  | * | 
|  | * @return True if successful, false otherwise. | 
|  | */ | 
|  | bool writeIspMode(); | 
|  |  | 
|  | /** | 
|  | * @brief Resets the ISP status to prepare for a firmware update. | 
|  | * | 
|  | * @return True if successful, false otherwise. | 
|  | */ | 
|  | bool writeIspStatusReset(); | 
|  |  | 
|  | /** | 
|  | * @brief Retrieves the path to the firmware file. | 
|  | * | 
|  | * @return True if successful, false otherwise. | 
|  | */ | 
|  | bool getFirmwarePath(); | 
|  |  | 
|  | /** | 
|  | * @brief Validates the firmware file. | 
|  | * | 
|  | * @return True if the file is valid, false otherwise. | 
|  | */ | 
|  | bool isFirmwareFileValid(); | 
|  |  | 
|  | /** | 
|  | * @brief Opens a firmware file in binary mode. | 
|  | * | 
|  | * @return A file stream to read the firmware | 
|  | * file. | 
|  | */ | 
|  | std::unique_ptr<std::ifstream> openFirmwareFile(); | 
|  |  | 
|  | /** | 
|  | * @brief Reads a block of firmware data from the file. | 
|  | * | 
|  | * @param file The input file stream from which to read data. | 
|  | * @param bytesToRead The number of bytes to read. | 
|  | * @return A vector containing the firmware block. | 
|  | */ | 
|  | std::vector<uint8_t> readFirmwareBlock(std::ifstream& file, | 
|  | const size_t& bytesToRead); | 
|  |  | 
|  | /** | 
|  | * @brief Prepares an ISP_MEMORY command block by processing the firmware | 
|  | * data block. | 
|  | * | 
|  | * @param dataBlockRead The firmware data block read from the file. | 
|  | */ | 
|  | void prepareCommandBlock(const std::vector<uint8_t>& dataBlockRead); | 
|  |  | 
|  | /** | 
|  | * @brief Performs firmware update for the power supply unit (PSU) | 
|  | * | 
|  | * This function retrieves the firmware file from appropriate path, | 
|  | * validate existence of the file and initiate the update process. | 
|  | * The process includes processing the data into blocks, and writes | 
|  | * these blocks to the PSU. | 
|  | * | 
|  | * @return True if firmware download was successful, false otherwise. | 
|  | */ | 
|  | bool downloadPsuFirmware(); | 
|  |  | 
|  | /** | 
|  | * @brief Performs an I2C write and read with retry logic. | 
|  | * | 
|  | * This function attempts to write a command block to PSU register | 
|  | * and read next block sequence and CML write status. If the block | 
|  | * sequence number the same as written block, then retry to write | 
|  | * same block again. | 
|  | * | 
|  | * @param regAddr The register address to write to. | 
|  | * @param expectedReadSize The size of data read from i2c device. | 
|  | * @param readData The buffer to store read data. | 
|  | * @param retries The number of retry attempts allowed. | 
|  | * @param delayTime The delay time between retries. | 
|  | * @return True if the operation is successful, false otherwise. | 
|  | */ | 
|  | bool performI2cWriteReadWithRetries( | 
|  | uint8_t regAddr, const uint8_t expectedReadSize, uint8_t* readData, | 
|  | const int retries, const int delayTime); | 
|  |  | 
|  | /** | 
|  | * @brief Performs a single I2C write and read without retry logic. | 
|  | * | 
|  | * @param regAddr The register address to write to. | 
|  | * @param readReplySize The size of data read from i2c device. | 
|  | * @param readData The buffer to store read data. | 
|  | * @param delayTime The delay time between write and read operations. | 
|  | */ | 
|  | void performI2cWriteRead(uint8_t regAddr, uint8_t& readReplySize, | 
|  | uint8_t* readData, const int& delayTime); | 
|  | /** | 
|  | * @brief Verifies the status of the firmware download. | 
|  | * | 
|  | * @return True if the download status is verified as successful, false | 
|  | * otherwise. | 
|  | */ | 
|  | bool verifyDownloadFWStatus(); | 
|  |  | 
|  | /** | 
|  | * @brief Initiates a reboot of the ISP to apply new firmware. | 
|  | */ | 
|  | void ispReboot(); | 
|  |  | 
|  | /** | 
|  | * @brief Reads the reboot status from the ISP. | 
|  | * | 
|  | * @return True if the reboot status indicates success, false | 
|  | * otherwise. | 
|  | */ | 
|  | bool ispReadRebootStatus(); | 
|  |  | 
|  | /** | 
|  | * @brief Pointer to the I2C interface for communication | 
|  | * | 
|  | * This pointer is not owned by the class. The caller is responsible for | 
|  | * ensuring that 'i2cInterface'  remains valid for the lifetime of this | 
|  | * object. Ensure to check this pointer for null before use. | 
|  | */ | 
|  | i2c::I2CInterface* i2cInterface; | 
|  |  | 
|  | /** | 
|  | * @brief Stores byte-swapped indices for command processing | 
|  | */ | 
|  | std::vector<uint8_t> byteSwappedIndex; | 
|  |  | 
|  | /** | 
|  | * @brief Command block used for writing data to the device | 
|  | */ | 
|  | std::vector<uint8_t> cmdBlockWrite; | 
|  |  | 
|  | /** | 
|  | * @brief The firmware file path | 
|  | */ | 
|  | std::string fspath; | 
|  | }; | 
|  | } // namespace aeiUpdater |