1 /** 2 * Copyright © 2019 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 "i2c_interface.hpp" 19 20 #include <sdbusplus/bus.hpp> 21 22 #include <filesystem> 23 #include <memory> 24 #include <string> 25 26 class TestUpdater; 27 28 namespace updater 29 { 30 31 namespace fs = std::filesystem; 32 33 constexpr auto FW_UPDATE_FAILED_MSG = 34 "xyz.openbmc_project.Power.PowerSupply.Error.FirmwareUpdateFailed"; 35 constexpr auto PSU_FW_FILE_ISSUE_MSG = 36 "xyz.openbmc_project.Power.PowerSupply.Error.FirmwareIssue"; 37 constexpr auto FW_UPDATE_SUCCESS_MSG = 38 "xyz.openbmc_project.Power.PowerSupply.Info.FirmwareUpdateSuccessful"; 39 40 constexpr auto ERROR_SEVERITY = "xyz.openbmc_project.Logging.Entry.Level.Error"; 41 constexpr auto INFORMATIONAL_SEVERITY = 42 "xyz.openbmc_project.Logging.Entry.Level.Informational"; 43 44 /** 45 * Update PSU firmware 46 * 47 * @param[in] bus - The sdbusplus DBus bus connection 48 * @param[in] psuInventoryPath - The inventory path of the PSU 49 * @param[in] imageDir - The directory containing the PSU image 50 * 51 * @return true if successful, otherwise false 52 */ 53 bool update(sdbusplus::bus_t& bus, const std::string& psuInventoryPath, 54 const std::string& imageDir); 55 56 class Updater 57 { 58 public: 59 friend TestUpdater; 60 Updater() = delete; 61 Updater(const Updater&) = delete; 62 Updater& operator=(const Updater&) = delete; 63 Updater(Updater&&) = default; 64 Updater& operator=(Updater&&) = default; 65 66 /** 67 * @brief Constructor 68 * 69 * @param psuInventoryPath - The PSU inventory path 70 * @param devPath - The PSU device path 71 * @param imageDir - The update image directory 72 */ 73 Updater(const std::string& psuInventoryPath, const std::string& devPath, 74 const std::string& imageDir); 75 76 /** @brief Destructor */ 77 virtual ~Updater() = default; 78 79 /** @brief Bind or unbind the driver 80 * 81 * @param doBind - indicate if it's going to bind or unbind the driver 82 */ 83 void bindUnbind(bool doBind); 84 85 /** @brief Set the PSU inventory present property 86 * 87 * @param present - The present state to set 88 */ 89 void setPresent(bool present); 90 91 /** @brief Check if it's ready to update the PSU 92 * 93 * @return true if it's ready, otherwise false 94 */ 95 bool isReadyToUpdate(); 96 97 /** @brief Do the PSU update 98 * 99 * @return 0 if success, otherwise non-zero 100 */ 101 virtual int doUpdate(); 102 103 /** @brief Create I2C device 104 * 105 * Creates the I2C device based on the device name. 106 * e.g. It opens busId 3, address 0x68 for "3-0068" 107 */ 108 void createI2CDevice(); 109 110 protected: 111 /** @brief Accessor for PSU inventory path */ getPsuInventoryPath() const112 const std::string& getPsuInventoryPath() const 113 { 114 return psuInventoryPath; 115 } 116 117 /** @brief Accessor for device path */ getDevPath() const118 const std::string& getDevPath() const 119 { 120 return devPath; 121 } 122 123 /** @brief Accessor for device name */ getDevName() const124 const std::string& getDevName() const 125 { 126 return devName; 127 } 128 129 /** @brief Accessor for image directory */ getImageDir() const130 const std::string& getImageDir() const 131 { 132 return imageDir; 133 } 134 135 /** @brief I2C interface accessor */ getI2C()136 i2c::I2CInterface* getI2C() 137 { 138 return i2c.get(); 139 } 140 141 /** 142 * @brief Creates a serviceable Predictive Event Log, 143 * 144 * This method generates an event log with the given error name, severity, 145 * and additional data. It interacts with the OpenBMC logging service to 146 * record faults. 147 * 148 * @param[in] errorName The name of the error to log. 149 * @param[in] severity The severity level of the error. 150 * @param[in] additionalData Additional key-value pairs containing details 151 * about the error. 152 */ 153 void createServiceableEventLog( 154 const std::string& errorName, const std::string& severity, 155 std::map<std::string, std::string>& additionalData); 156 157 /** 158 * @brief Retrieves additional data related to I2C communication. 159 * 160 * This method collects and returns I2C bus information, including the 161 * bus ID, address, and error number, which are used for reporting 162 * Predictive Error Log. 163 * 164 * @return A map containing I2C-related key-value pairs. 165 */ 166 std::map<std::string, std::string> getI2CAdditionalData(); 167 168 /** 169 * @brief Call out an I2C-related Predictive Error Log. 170 * 171 * This method creates a serviceable event log related to I2C failures. 172 * It collects additional data about the I2C communication and logs the 173 * failure with appropriate severity. 174 * 175 * @param[in] extraAdditionalData Additional key-value pairs specific to 176 * the error context. 177 * @param[in] exceptionString A string describing the exception that 178 * triggered the error. 179 * @param[in] errorCode Exception error code. 180 */ 181 void callOutI2CEventLog( 182 std::map<std::string, std::string> extraAdditionalData, 183 const std::string& exceptionString = "", const int errorCode = 0); 184 185 /** 186 * @brief Call out a PSU-related Predictive Error Log. 187 * 188 * This method logs a failure related to PSU firmware updates and additional 189 * diagnostics data to the event log. 190 * 191 * @param[in] extraAdditionalData Additional key-value pairs specific to 192 * the PSU-related error. 193 */ 194 void callOutPsuEventLog( 195 std::map<std::string, std::string> extraAdditionalData); 196 197 /** 198 * @brief Call out a software-related Predictive Error Log. 199 * 200 * This method logs a failure related to PSU firmware file issues or other 201 * software-related errors. It merges any additional error-specific data 202 * before logging the event. 203 * 204 * @param[in] extraAdditionalData Additional key-value pairs specific to 205 * the software-related error. 206 */ 207 void callOutSWEventLog( 208 std::map<std::string, std::string> extraAdditionalData); 209 210 /** 211 * @brief Accessor to set logEventLog to true 212 * 213 */ enableEventLogging()214 void enableEventLogging() 215 { 216 eventLogState = true; 217 } 218 219 /** 220 * @brief Accessor to set eventLogState to false 221 * 222 */ disableEventLogging()223 void disableEventLogging() 224 { 225 eventLogState = false; 226 } 227 228 /** 229 * @brief Accessor eventLogState status (enable true, disable false) 230 * 231 * @return true or false 232 */ isEventLogEnabled()233 bool isEventLogEnabled() 234 { 235 return eventLogState; 236 } 237 238 /** 239 * @brief Accessor to disable eventLoggedThisSession 240 * 241 */ enableEventLoggedThisSession()242 void enableEventLoggedThisSession() 243 { 244 eventLoggedThisSession = true; 245 } 246 247 /** 248 * @brief Accessor to retieve eventLoggedThisSession status 249 * 250 * @return true or false 251 */ isEventLoggedThisSession()252 bool isEventLoggedThisSession() 253 { 254 return eventLoggedThisSession; 255 } 256 257 /** 258 * @brief Call out successful PSU firmware update. 259 * 260 */ 261 void callOutGoodEventLog(); 262 263 private: 264 /** @brief The sdbusplus DBus bus connection */ 265 sdbusplus::bus_t bus; 266 267 /** @brief The PSU inventory path */ 268 std::string psuInventoryPath; 269 270 /** @brief The PSU device path 271 * 272 * Usually it is a device in i2c subsystem, e.g. 273 * /sys/bus/i2c/devices/3-0068 274 */ 275 std::string devPath; 276 277 /** @brief The PSU device name 278 * 279 * Usually it is a i2c device name, e.g. 280 * 3-0068 281 */ 282 std::string devName; 283 284 /** @brief The PSU image directory */ 285 std::string imageDir; 286 287 /** @brief The PSU device driver's path 288 * 289 * Usually it is the PSU driver, e.g. 290 * /sys/bus/i2c/drivers/ibm-cffps 291 */ 292 fs::path driverPath; 293 294 /** @brief The i2c device interface */ 295 std::unique_ptr<i2c::I2CInterface> i2c; 296 297 /** @brief Event Log flag */ 298 bool eventLogState = false; 299 300 /** @brief Event logged this session flag, this is to make sure no other 301 * event log can be logged 302 */ 303 bool eventLoggedThisSession = false; 304 }; 305 306 namespace internal 307 { 308 309 /** 310 * @brief Factory function to create an Updater instance based on PSU model 311 * number 312 * 313 * @param[in] model - PSU model number 314 * @param[in] psuInventoryPath - PSU inventory path 315 * @param[in] devPath - Device path 316 * @param[in] imageDir - Image directory 317 * 318 * return pointer class based on the device PSU model. 319 */ 320 std::unique_ptr<updater::Updater> getClassInstance( 321 const std::string& model, const std::string& psuInventoryPath, 322 const std::string& devPath, const std::string& imageDir); 323 324 /** 325 * @brief Retrieve the firmware filename path in the specified directory 326 * 327 * @param[in] directory - Path to FS directory 328 * 329 * @retun filename or null 330 */ 331 const std::string getFWFilenamePath(const std::string& directory); 332 333 /** 334 * @brief Calculate CRC-8 for a data vector 335 * 336 * @param[in] data - Firmware data block 337 * 338 * @return CRC8 339 */ 340 uint8_t calculateCRC8(const std::vector<uint8_t>& data); 341 342 /** 343 * @brief Delay execution in milliseconds 344 * 345 * @param[in] milliseconds - Time in milliseconds 346 */ 347 void delay(const int& milliseconds); 348 349 /** 350 * @brief Convert a big-endian value to little-endian 351 * 352 * @param[in] bigEndianValue - Uint 32 bit value 353 * 354 * @return vector of little endians. 355 */ 356 std::vector<uint8_t> bigEndianToLittleEndian(const uint32_t bigEndianValue); 357 358 /** 359 * @brief Validate the existence and size of a firmware file. 360 * 361 * @param[in] fileName - Firmware file name 362 * 363 * @return true for success or false 364 */ 365 bool validateFWFile(const std::string& fileName); 366 367 /** 368 * @brief Open a firmware file for reading in binary mode. 369 * 370 * @param[in] fileName - Firmware file name 371 * 372 * @return pointer to firmware file stream 373 */ 374 std::unique_ptr<std::ifstream> openFirmwareFile(const std::string& fileName); 375 376 /** 377 * @brief Read firmware bytes from file. 378 * 379 * @param[in] inputFile - Input file stream 380 * @param[in] numberOfBytesToRead - Number of bytes to read from firmware file. 381 * 382 * @return vector of data read 383 */ 384 std::vector<uint8_t> readFirmwareBytes(std::ifstream& inputFile, 385 const size_t numberOfBytesToRead); 386 387 } // namespace internal 388 } // namespace updater 389