blob: 1732f868d335fd20f70c0b429dcbaeead4f15df3 [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"
Faisal Awadaec61bbd2024-11-04 08:46:20 -060019#include "version.hpp"
Lei YU7c2fbbb2019-11-06 14:56:02 +080020
Lei YU9ab6d752019-10-28 17:03:20 +080021#include <sdbusplus/bus.hpp>
Brandon Wymand1bc4ce2019-12-13 14:20:34 -060022
Faisal Awadaec61bbd2024-11-04 08:46:20 -060023#include <chrono>
Brandon Wymand1bc4ce2019-12-13 14:20:34 -060024#include <filesystem>
Faisal Awadaec61bbd2024-11-04 08:46:20 -060025#include <memory>
Lei YUd19df252019-10-25 17:31:52 +080026#include <string>
Faisal Awadaec61bbd2024-11-04 08:46:20 -060027#include <thread>
Lei YUd19df252019-10-25 17:31:52 +080028
Lei YU7c2fbbb2019-11-06 14:56:02 +080029class TestUpdater;
30
Lei YUd19df252019-10-25 17:31:52 +080031namespace updater
32{
33
Lei YU9ab6d752019-10-28 17:03:20 +080034namespace fs = std::filesystem;
35
Lei YUd19df252019-10-25 17:31:52 +080036/**
37 * Update PSU firmware
38 *
Faisal Awadaec61bbd2024-11-04 08:46:20 -060039 * @param[in] bus - The sdbusplus DBus bus connection
Lei YUd19df252019-10-25 17:31:52 +080040 * @param[in] psuInventoryPath - The inventory path of the PSU
41 * @param[in] imageDir - The directory containing the PSU image
42 *
43 * @return true if successful, otherwise false
44 */
Faisal Awadaec61bbd2024-11-04 08:46:20 -060045bool update(sdbusplus::bus_t& bus, const std::string& psuInventoryPath,
46 const std::string& imageDir);
Lei YUd19df252019-10-25 17:31:52 +080047
Lei YU9ab6d752019-10-28 17:03:20 +080048class Updater
49{
50 public:
Lei YU7c2fbbb2019-11-06 14:56:02 +080051 friend TestUpdater;
Lei YU9ab6d752019-10-28 17:03:20 +080052 Updater() = delete;
53 Updater(const Updater&) = delete;
54 Updater& operator=(const Updater&) = delete;
55 Updater(Updater&&) = default;
56 Updater& operator=(Updater&&) = default;
57
58 /**
59 * @brief Constructor
60 *
61 * @param psuInventoryPath - The PSU inventory path
62 * @param devPath - The PSU device path
63 * @param imageDir - The update image directory
64 */
65 Updater(const std::string& psuInventoryPath, const std::string& devPath,
66 const std::string& imageDir);
67
68 /** @brief Destructor */
Faisal Awadaec61bbd2024-11-04 08:46:20 -060069 virtual ~Updater() = default;
Lei YU9ab6d752019-10-28 17:03:20 +080070
71 /** @brief Bind or unbind the driver
72 *
73 * @param doBind - indicate if it's going to bind or unbind the driver
74 */
75 void bindUnbind(bool doBind);
76
77 /** @brief Set the PSU inventory present property
78 *
79 * @param present - The present state to set
80 */
81 void setPresent(bool present);
82
Lei YU575ed132019-10-29 17:22:16 +080083 /** @brief Check if it's ready to update the PSU
84 *
85 * @return true if it's ready, otherwise false
86 */
87 bool isReadyToUpdate();
88
Lei YU9ab6d752019-10-28 17:03:20 +080089 /** @brief Do the PSU update
90 *
91 * @return 0 if success, otherwise non-zero
92 */
Faisal Awadaec61bbd2024-11-04 08:46:20 -060093 virtual int doUpdate();
Lei YU9ab6d752019-10-28 17:03:20 +080094
Lei YU7c2fbbb2019-11-06 14:56:02 +080095 /** @brief Create I2C device
96 *
97 * Creates the I2C device based on the device name.
98 * e.g. It opens busId 3, address 0x68 for "3-0068"
99 */
100 void createI2CDevice();
101
Faisal Awadaec61bbd2024-11-04 08:46:20 -0600102 protected:
103 /** @brief Accessor for PSU inventory path */
104 const std::string& getPsuInventoryPath() const
105 {
106 return psuInventoryPath;
107 }
108
109 /** @brief Accessor for device path */
110 const std::string& getDevPath() const
111 {
112 return devPath;
113 }
114
115 /** @brief Accessor for device name */
116 const std::string& getDevName() const
117 {
118 return devName;
119 }
120
121 /** @brief Accessor for image directory */
122 const std::string& getImageDir() const
123 {
124 return imageDir;
125 }
126
127 /** @brief I2C interface accessor */
128 i2c::I2CInterface* getI2C()
129 {
130 return i2c.get();
131 }
132
Lei YU9ab6d752019-10-28 17:03:20 +0800133 private:
134 /** @brief The sdbusplus DBus bus connection */
Patrick Williams7354ce62022-07-22 19:26:56 -0500135 sdbusplus::bus_t bus;
Lei YU9ab6d752019-10-28 17:03:20 +0800136
137 /** @brief The PSU inventory path */
138 std::string psuInventoryPath;
139
140 /** @brief The PSU device path
141 *
142 * Usually it is a device in i2c subsystem, e.g.
143 * /sys/bus/i2c/devices/3-0068
144 */
145 std::string devPath;
146
147 /** @brief The PSU device name
148 *
149 * Usually it is a i2c device name, e.g.
150 * 3-0068
151 */
152 std::string devName;
153
154 /** @brief The PSU image directory */
155 std::string imageDir;
156
157 /** @brief The PSU device driver's path
158 *
159 * Usually it is the PSU driver, e.g.
160 * /sys/bus/i2c/drivers/ibm-cffps
161 */
162 fs::path driverPath;
Lei YU7c2fbbb2019-11-06 14:56:02 +0800163
164 /** @brief The i2c device interface */
165 std::unique_ptr<i2c::I2CInterface> i2c;
Lei YU9ab6d752019-10-28 17:03:20 +0800166};
167
Faisal Awadaec61bbd2024-11-04 08:46:20 -0600168namespace internal
169{
170
171/**
172 * @brief Get the device name from the device path
173 *
174 * @param[in] devPath - PSU path
175 *
176 * @return device name e.g. 3-0068
177 */
178std::string getDeviceName(std::string devPath);
179
180/**
181 * @brief Function to get device path using DBus bus and PSU
182 * inventory Path
183 *
184 * @param[in] bus - The sdbusplus DBus bus connection
185 * @param[in] psuInventoryPath - PSU inventory path
186 *
187 * @return device path e.g. /sys/bus/i2c/devices/3-0068
188 */
189std::string getDevicePath(sdbusplus::bus_t& bus,
190 const std::string& psuInventoryPath);
191
192/**
193 * @brief Parse the device name to obtain bus and device address
194 *
195 * @param[in] devName - Device name
196 *
197 * @return bus and device address
198 */
199std::pair<uint8_t, uint8_t> parseDeviceName(const std::string& devName);
200
201/**
202 * @brief Factory function to create an Updater instance based on PSU model
203 * number
204 *
205 * @param[in] model - PSU model number
206 * @param[in] psuInventoryPath - PSU inventory path
207 * @param[in] devPath - Device path
208 * @param[in] imageDir - Image directory
209 *
210 * return pointer class based on the device PSU model.
211 */
212std::unique_ptr<updater::Updater> getClassInstance(
213 const std::string& model, const std::string& psuInventoryPath,
214 const std::string& devPath, const std::string& imageDir);
215
216/**
217 * @brief Retrieve the firmware filename path in the specified directory
218 *
219 * @param[in] directory - Path to FS directory
220 *
221 * @retun filename or null
222 */
223const std::string getFWFilenamePath(const std::string& directory);
224
225/**
226 * @brief Calculate CRC-8 for a data vector
227 *
228 * @param[in] data - Firmware data block
229 *
230 * @return CRC8
231 */
232uint8_t calculateCRC8(const std::vector<uint8_t>& data);
233
234/**
235 * @brief Delay execution in milliseconds
236 *
237 * @param[in] milliseconds - Time in milliseconds
238 */
239void delay(const int& milliseconds);
240
241/**
242 * @brief Convert a big-endian value to little-endian
243 *
244 * @param[in] bigEndianValue - Uint 32 bit value
245 *
246 * @return vector of little endians.
247 */
248std::vector<uint8_t> bigEndianToLittleEndian(const uint32_t bigEndianValue);
249
250/**
251 * @brief Validate the existence and size of a firmware file.
252 *
253 * @param[in] fileName - Firmware file name
254 *
255 * @return true for success or false
256 */
257bool validateFWFile(const std::string& fileName);
258
259/**
260 * @brief Open a firmware file for reading in binary mode.
261 *
262 * @param[in] fileName - Firmware file name
263 *
264 * @return pointer to firmware file stream
265 */
266std::unique_ptr<std::ifstream> openFirmwareFile(const std::string& fileName);
267
268/**
269 * @brief Read firmware bytes from file.
270 *
271 * @param[in] inputFile - Input file stream
272 * @param[in] numberOfBytesToRead - Number of bytes to read from firmware file.
273 *
274 * @return vector of data read
275 */
276std::vector<uint8_t> readFirmwareBytes(std::ifstream& inputFile,
277 const size_t numberOfBytesToRead);
278
279/**
280 * @brief Wrapper to check existence of PSU JSON file
281 *
282 * @return true or false (true if using JSON file)
283 */
284bool usePsuJsonFile();
285} // namespace internal
Lei YUd19df252019-10-25 17:31:52 +0800286} // namespace updater