blob: 21bc4cde8e4bbff4eef7f9beede1ebbdbb4d1a5e [file] [log] [blame]
Lei YUd19df252019-10-25 17:31:52 +08001/**
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
Lei YU7c2fbbb2019-11-06 14:56:02 +080018#include "i2c_interface.hpp"
19
Lei YU9ab6d752019-10-28 17:03:20 +080020#include <sdbusplus/bus.hpp>
Brandon Wymand1bc4ce2019-12-13 14:20:34 -060021
22#include <filesystem>
Faisal Awadaec61bbd2024-11-04 08:46:20 -060023#include <memory>
Lei YUd19df252019-10-25 17:31:52 +080024#include <string>
25
Lei YU7c2fbbb2019-11-06 14:56:02 +080026class TestUpdater;
27
Lei YUd19df252019-10-25 17:31:52 +080028namespace updater
29{
30
Lei YU9ab6d752019-10-28 17:03:20 +080031namespace fs = std::filesystem;
32
Faisal Awada57fb6642025-02-21 16:52:54 -060033constexpr auto FW_UPDATE_FAILED_MSG =
34 "xyz.openbmc_project.Power.PowerSupply.Error.FirmwareUpdateFailed";
35constexpr auto PSU_FW_FILE_ISSUE_MSG =
36 "xyz.openbmc_project.Power.PowerSupply.Error.FirmwareIssue";
37constexpr auto FW_UPDATE_SUCCESS_MSG =
38 "xyz.openbmc_project.Power.PowerSupply.Info.FirmwareUpdateSuccessful";
39
40constexpr auto ERROR_SEVERITY = "xyz.openbmc_project.Logging.Entry.Level.Error";
41constexpr auto INFORMATIONAL_SEVERITY =
42 "xyz.openbmc_project.Logging.Entry.Level.Informational";
43
Lei YUd19df252019-10-25 17:31:52 +080044/**
45 * Update PSU firmware
46 *
Faisal Awadaec61bbd2024-11-04 08:46:20 -060047 * @param[in] bus - The sdbusplus DBus bus connection
Lei YUd19df252019-10-25 17:31:52 +080048 * @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 */
Faisal Awadaec61bbd2024-11-04 08:46:20 -060053bool update(sdbusplus::bus_t& bus, const std::string& psuInventoryPath,
54 const std::string& imageDir);
Lei YUd19df252019-10-25 17:31:52 +080055
Lei YU9ab6d752019-10-28 17:03:20 +080056class Updater
57{
58 public:
Lei YU7c2fbbb2019-11-06 14:56:02 +080059 friend TestUpdater;
Lei YU9ab6d752019-10-28 17:03:20 +080060 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 */
Faisal Awadaec61bbd2024-11-04 08:46:20 -060077 virtual ~Updater() = default;
Lei YU9ab6d752019-10-28 17:03:20 +080078
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
Lei YU575ed132019-10-29 17:22:16 +080091 /** @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
Lei YU9ab6d752019-10-28 17:03:20 +080097 /** @brief Do the PSU update
98 *
99 * @return 0 if success, otherwise non-zero
100 */
Faisal Awadaec61bbd2024-11-04 08:46:20 -0600101 virtual int doUpdate();
Lei YU9ab6d752019-10-28 17:03:20 +0800102
Lei YU7c2fbbb2019-11-06 14:56:02 +0800103 /** @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
Faisal Awadaec61bbd2024-11-04 08:46:20 -0600110 protected:
111 /** @brief Accessor for PSU inventory path */
112 const std::string& getPsuInventoryPath() const
113 {
114 return psuInventoryPath;
115 }
116
117 /** @brief Accessor for device path */
118 const std::string& getDevPath() const
119 {
120 return devPath;
121 }
122
123 /** @brief Accessor for device name */
124 const std::string& getDevName() const
125 {
126 return devName;
127 }
128
129 /** @brief Accessor for image directory */
130 const std::string& getImageDir() const
131 {
132 return imageDir;
133 }
134
135 /** @brief I2C interface accessor */
136 i2c::I2CInterface* getI2C()
137 {
138 return i2c.get();
139 }
140
Faisal Awada57fb6642025-02-21 16:52:54 -0600141 /**
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 */
214 void enableEventLogging()
215 {
216 eventLogState = true;
217 }
218
219 /**
220 * @brief Accessor to set eventLogState to false
221 *
222 */
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 */
233 bool isEventLogEnabled()
234 {
235 return eventLogState;
236 }
237
238 /**
239 * @brief Accessor to disable eventLoggedThisSession
240 *
241 */
242 void enableEventLoggedThisSession()
243 {
244 eventLoggedThisSession = true;
245 }
246
247 /**
248 * @brief Accessor to retieve eventLoggedThisSession status
249 *
250 * @return true or false
251 */
252 bool isEventLoggedThisSession()
253 {
254 return eventLoggedThisSession;
255 }
256
257 /**
258 * @brief Call out successful PSU firmware update.
259 *
260 */
261 void callOutGoodEventLog();
262
Lei YU9ab6d752019-10-28 17:03:20 +0800263 private:
264 /** @brief The sdbusplus DBus bus connection */
Patrick Williams7354ce62022-07-22 19:26:56 -0500265 sdbusplus::bus_t bus;
Lei YU9ab6d752019-10-28 17:03:20 +0800266
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;
Lei YU7c2fbbb2019-11-06 14:56:02 +0800293
294 /** @brief The i2c device interface */
295 std::unique_ptr<i2c::I2CInterface> i2c;
Faisal Awada57fb6642025-02-21 16:52:54 -0600296
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;
Lei YU9ab6d752019-10-28 17:03:20 +0800304};
305
Faisal Awadaec61bbd2024-11-04 08:46:20 -0600306namespace internal
307{
308
309/**
Faisal Awadaec61bbd2024-11-04 08:46:20 -0600310 * @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 */
320std::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 */
331const 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 */
340uint8_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 */
347void 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 */
356std::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 */
365bool 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 */
374std::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 */
384std::vector<uint8_t> readFirmwareBytes(std::ifstream& inputFile,
385 const size_t numberOfBytesToRead);
386
Faisal Awadaec61bbd2024-11-04 08:46:20 -0600387} // namespace internal
Lei YUd19df252019-10-25 17:31:52 +0800388} // namespace updater