1 /** 2 * Copyright © 2024 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "updater.hpp" 19 20 namespace aeiUpdater 21 { 22 /** 23 * @class AeiUpdater 24 * @brief A class to handle firmware updates for the AEI PSUs. 25 * 26 * This class provides methods to update firmware by writing ISP keys, 27 * validating firmware files, and performing I2C communications. It includes 28 * functions to manage the update process, including downloading firmware blocks 29 * and verifying the update status. 30 */ 31 class AeiUpdater : public updater::Updater 32 { 33 public: 34 AeiUpdater() = delete; 35 AeiUpdater(const AeiUpdater&) = delete; 36 AeiUpdater(AeiUpdater&&) = delete; 37 AeiUpdater& operator=(const AeiUpdater&) = delete; 38 AeiUpdater& operator=(AeiUpdater&&) = delete; 39 ~AeiUpdater() = default; 40 41 /** 42 * @brief Constructor for the AeiUpdater class. 43 * 44 * @param psuInventoryPath The path to the PSU's inventory in the system. 45 * @param devPath The device path for the PSU. 46 * @param imageDir The directory containing the firmware image files. 47 */ AeiUpdater(const std::string & psuInventoryPath,const std::string & devPath,const std::string & imageDir)48 AeiUpdater(const std::string& psuInventoryPath, const std::string& devPath, 49 const std::string& imageDir) : 50 Updater(psuInventoryPath, devPath, imageDir) 51 {} 52 53 /** 54 * @brief Initiates the firmware update process. 55 * 56 * @return Status code 0 for success or 1 for failure. 57 */ 58 int doUpdate() override; 59 60 private: 61 /** 62 * @brief Writes an ISP (In-System Programming) key to initiate the update. 63 * 64 * @return True if successful, false otherwise. 65 */ 66 bool writeIspKey(); 67 68 /** 69 * @brief Writes the mode required for ISP to start firmware programming. 70 * 71 * @return True if successful, false otherwise. 72 */ 73 bool writeIspMode(); 74 75 /** 76 * @brief Resets the ISP status to prepare for a firmware update. 77 * 78 * @return True if successful, false otherwise. 79 */ 80 bool writeIspStatusReset(); 81 82 /** 83 * @brief Retrieves the path to the firmware file. 84 * 85 * @return True if successful, false otherwise. 86 */ 87 bool getFirmwarePath(); 88 89 /** 90 * @brief Validates the firmware file. 91 * 92 * @return True if the file is valid, false otherwise. 93 */ 94 bool isFirmwareFileValid(); 95 96 /** 97 * @brief Opens a firmware file in binary mode. 98 * 99 * @return A file stream to read the firmware 100 * file. 101 */ 102 std::unique_ptr<std::ifstream> openFirmwareFile(); 103 104 /** 105 * @brief Reads a block of firmware data from the file. 106 * 107 * @param file The input file stream from which to read data. 108 * @param bytesToRead The number of bytes to read. 109 * @return A vector containing the firmware block. 110 */ 111 std::vector<uint8_t> readFirmwareBlock(std::ifstream& file, 112 const size_t& bytesToRead); 113 114 /** 115 * @brief Prepares an ISP_MEMORY command block by processing the firmware 116 * data block. 117 * 118 * @param dataBlockRead The firmware data block read from the file. 119 */ 120 void prepareCommandBlock(const std::vector<uint8_t>& dataBlockRead); 121 122 /** 123 * @brief Performs firmware update for the power supply unit (PSU) 124 * 125 * This function retrieves the firmware file from appropriate path, 126 * validate existence of the file and initiate the update process. 127 * The process includes processing the data into blocks, and writes 128 * these blocks to the PSU. 129 * 130 * @return True if firmware download was successful, false otherwise. 131 */ 132 bool downloadPsuFirmware(); 133 134 /** 135 * @brief Performs an I2C write and read with retry logic. 136 * 137 * This function attempts to write a command block to PSU register 138 * and read next block sequence and CML write status. If the block 139 * sequence number the same as written block, then retry to write 140 * same block again. 141 * 142 * @param regAddr The register address to write to. 143 * @param expectedReadSize The size of data read from i2c device. 144 * @param readData The buffer to store read data. 145 * @param retries The number of retry attempts allowed. 146 * @param delayTime The delay time between retries. 147 * @return True if the operation is successful, false otherwise. 148 */ 149 bool performI2cWriteReadWithRetries( 150 uint8_t regAddr, const uint8_t expectedReadSize, uint8_t* readData, 151 const int retries, const int delayTime); 152 153 /** 154 * @brief Performs a single I2C write and read without retry logic. 155 * 156 * @param regAddr The register address to write to. 157 * @param readReplySize The size of data read from i2c device. 158 * @param readData The buffer to store read data. 159 * @param delayTime The delay time between write and read operations. 160 */ 161 void performI2cWriteRead(uint8_t regAddr, uint8_t& readReplySize, 162 uint8_t* readData, const int& delayTime); 163 /** 164 * @brief Verifies the status of the firmware download. 165 * 166 * @return True if the download status is verified as successful, false 167 * otherwise. 168 */ 169 bool verifyDownloadFWStatus(); 170 171 /** 172 * @brief Initiates a reboot of the ISP to apply new firmware. 173 */ 174 void ispReboot(); 175 176 /** 177 * @brief Reads the reboot status from the ISP. 178 * 179 * @return True if the reboot status indicates success, false 180 * otherwise. 181 */ 182 bool ispReadRebootStatus(); 183 184 /** 185 * @brief Pointer to the I2C interface for communication 186 * 187 * This pointer is not owned by the class. The caller is responsible for 188 * ensuring that 'i2cInterface' remains valid for the lifetime of this 189 * object. Ensure to check this pointer for null before use. 190 */ 191 i2c::I2CInterface* i2cInterface; 192 193 /** 194 * @brief Stores byte-swapped indices for command processing 195 */ 196 std::vector<uint8_t> byteSwappedIndex; 197 198 /** 199 * @brief Command block used for writing data to the device 200 */ 201 std::vector<uint8_t> cmdBlockWrite; 202 203 /** 204 * @brief The firmware file path 205 */ 206 std::string fspath; 207 }; 208 } // namespace aeiUpdater 209