blob: 0853d48a7a7528799a6641f82f59be458e77889e [file] [log] [blame]
Deepak Kodihallif6d3a832019-11-19 07:00:29 -06001#pragma once
2
3#include "config.h"
4
5#include "file_io_by_type.hpp"
6
Adriana Kobylak6876f122019-12-12 09:49:56 -06007#include <filesystem>
Deepak Kodihallif6d3a832019-11-19 07:00:29 -06008#include <sstream>
9#include <string>
10
11namespace pldm
12{
13namespace responder
14{
15
Adriana Kobylak6876f122019-12-12 09:49:56 -060016namespace fs = std::filesystem;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060017
Sampa Misra3a0e3b92020-10-21 05:58:00 -050018using MarkerLIDremainingSize = uint64_t;
19
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060020/** @class LidHandler
21 *
22 * @brief Inherits and implements FileHandler. This class is used
23 * to read/write LIDs.
24 */
25class LidHandler : public FileHandler
26{
27 public:
28 /** @brief LidHandler constructor
29 */
Sampa Misra3a0e3b92020-10-21 05:58:00 -050030 LidHandler(uint32_t fileHandle, bool permSide, uint8_t lidType = 0) :
31 FileHandler(fileHandle), lidType(lidType)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060032 {
Sampa Misra69508502020-09-08 00:08:21 -050033 sideToRead = permSide ? Pside : Tside;
34 isPatchDir = false;
Adriana Kobylak76f820c2020-07-16 11:02:03 -050035 std::string dir = permSide ? LID_ALTERNATE_DIR : LID_RUNNING_DIR;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060036 std::stringstream stream;
37 stream << std::hex << fileHandle;
Adriana Kobylak6876f122019-12-12 09:49:56 -060038 auto lidName = stream.str() + ".lid";
Deepak Kodihalli09b017b2020-08-26 07:37:32 -050039 std::string patchDir =
40 permSide ? LID_ALTERNATE_PATCH_DIR : LID_RUNNING_PATCH_DIR;
41 auto patch = fs::path(patchDir) / lidName;
42 if (fs::is_regular_file(patch))
Adriana Kobylak6876f122019-12-12 09:49:56 -060043 {
44 lidPath = patch;
Sampa Misra69508502020-09-08 00:08:21 -050045 isPatchDir = true;
Adriana Kobylak6876f122019-12-12 09:49:56 -060046 }
47 else
48 {
49 lidPath = std::move(dir) + '/' + lidName;
50 }
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060051 }
52
Sampa Misra69508502020-09-08 00:08:21 -050053 /** @brief Method to construct the LID path based on current boot side
54 * @param[in] oemPlatformHandler - OEM platform handler
55 * @return bool - true if a new path is constructed
56 */
57 bool constructLIDPath(oem_platform::Handler* oemPlatformHandler)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060058 {
Sampa Misra69508502020-09-08 00:08:21 -050059 if (oemPlatformHandler != nullptr)
60 {
61 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
62 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
63 oemPlatformHandler);
64 std::string dir = LID_ALTERNATE_DIR;
65 if (isPatchDir)
66 {
67 dir = LID_ALTERNATE_PATCH_DIR;
68 }
69 if (oemIbmPlatformHandler->codeUpdate->fetchCurrentBootSide() ==
70 sideToRead)
71 {
72 if (isPatchDir)
73 {
74 dir = LID_RUNNING_PATCH_DIR;
75 }
76 else
77 {
78 dir = LID_RUNNING_DIR;
79 }
80 }
81 else if (oemIbmPlatformHandler->codeUpdate
82 ->isCodeUpdateInProgress())
83 {
84 return false;
85 }
86
87 std::stringstream stream;
88 stream << std::hex << fileHandle;
89 auto lidName = stream.str() + ".lid";
90 lidPath = std::move(dir) + '/' + lidName;
91 }
92 return true;
93 }
94
95 virtual int writeFromMemory(uint32_t offset, uint32_t length,
96 uint64_t address,
97 oem_platform::Handler* oemPlatformHandler)
98 {
Sampa Misra3a0e3b92020-10-21 05:58:00 -050099 int rc = PLDM_SUCCESS;
100 bool codeUpdateInProgress = false;
Sampa Misra69508502020-09-08 00:08:21 -0500101 if (oemPlatformHandler != nullptr)
102 {
103 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
104 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
105 oemPlatformHandler);
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500106 codeUpdateInProgress =
107 oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress();
108 if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER)
Sampa Misra69508502020-09-08 00:08:21 -0500109 {
110 std::string dir = LID_STAGING_DIR;
111 std::stringstream stream;
112 stream << std::hex << fileHandle;
113 auto lidName = stream.str() + ".lid";
114 lidPath = std::move(dir) + '/' + lidName;
115 }
116 }
Sampa Misra69508502020-09-08 00:08:21 -0500117 bool fileExists = fs::exists(lidPath);
118 int flags{};
119 if (fileExists)
120 {
121 flags = O_RDWR;
122 }
123 else
124 {
125 flags = O_WRONLY | O_CREAT | O_TRUNC | O_SYNC;
126 }
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600127 auto fd = open(lidPath.c_str(), flags, S_IRUSR);
Sampa Misra69508502020-09-08 00:08:21 -0500128 if (fd == -1)
129 {
130 std::cerr << "Could not open file for writing " << lidPath.c_str()
131 << "\n";
132 return PLDM_ERROR;
133 }
134 close(fd);
135
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500136 rc = transferFileData(lidPath, false, offset, length, address);
Sampa Misra69508502020-09-08 00:08:21 -0500137 if (rc != PLDM_SUCCESS)
138 {
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500139 std::cerr << "writeFileFromMemory failed with rc= " << rc << " \n";
Sampa Misra69508502020-09-08 00:08:21 -0500140 return rc;
141 }
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500142 if (lidType == PLDM_FILE_TYPE_LID_MARKER)
143 {
144 markerLIDremainingSize -= length;
145 if (markerLIDremainingSize == 0)
146 {
147 pldm::responder::oem_ibm_platform::Handler*
148 oemIbmPlatformHandler = dynamic_cast<
149 pldm::responder::oem_ibm_platform::Handler*>(
150 oemPlatformHandler);
151 auto sensorId =
152 oemIbmPlatformHandler->codeUpdate->getMarkerLidSensor();
153 using namespace pldm::responder::oem_ibm_platform;
154 oemIbmPlatformHandler->sendStateSensorEvent(
155 sensorId, PLDM_STATE_SENSOR_STATE, 0, VALID, VALID);
156 // rc = validate api;
157 rc = PLDM_SUCCESS;
158 }
159 }
160 else if (codeUpdateInProgress)
161 {
162 rc = processCodeUpdateLid(lidPath);
163 }
Sampa Misra69508502020-09-08 00:08:21 -0500164 return rc;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600165 }
166
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600167 virtual int readIntoMemory(uint32_t offset, uint32_t& length,
Sampa Misra69508502020-09-08 00:08:21 -0500168 uint64_t address,
169 oem_platform::Handler* oemPlatformHandler)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600170 {
Sampa Misra69508502020-09-08 00:08:21 -0500171 if (constructLIDPath(oemPlatformHandler))
172 {
173 return transferFileData(lidPath, true, offset, length, address);
174 }
175 return PLDM_ERROR;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600176 }
177
Sampa Misra69508502020-09-08 00:08:21 -0500178 virtual int write(const char* buffer, uint32_t offset, uint32_t& length,
179 oem_platform::Handler* oemPlatformHandler)
Sampa Misra18967162020-01-14 02:31:41 -0600180 {
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500181 int rc = PLDM_SUCCESS;
182 bool codeUpdateInProgress = false;
Sampa Misra69508502020-09-08 00:08:21 -0500183 if (oemPlatformHandler != nullptr)
184 {
185 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
186 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
187 oemPlatformHandler);
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500188 codeUpdateInProgress =
189 oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress();
190 if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER)
Sampa Misra69508502020-09-08 00:08:21 -0500191 {
192 std::string dir = LID_STAGING_DIR;
193 std::stringstream stream;
194 stream << std::hex << fileHandle;
195 auto lidName = stream.str() + ".lid";
196 lidPath = std::move(dir) + '/' + lidName;
197 }
198 }
Sampa Misra69508502020-09-08 00:08:21 -0500199 bool fileExists = fs::exists(lidPath);
200 int flags{};
201 if (fileExists)
202 {
203 flags = O_RDWR;
204 size_t fileSize = fs::file_size(lidPath);
205 if (offset > fileSize)
206 {
207 std::cerr << "Offset exceeds file size, OFFSET=" << offset
208 << " FILE_SIZE=" << fileSize << "\n";
209 return PLDM_DATA_OUT_OF_RANGE;
210 }
211 }
212 else
213 {
214 flags = O_WRONLY | O_CREAT | O_TRUNC | O_SYNC;
215 if (offset > 0)
216 {
217 std::cerr << "Offset is non zero in a new file \n";
218 return PLDM_DATA_OUT_OF_RANGE;
219 }
220 }
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600221 auto fd = open(lidPath.c_str(), flags, S_IRUSR);
Sampa Misra69508502020-09-08 00:08:21 -0500222 if (fd == -1)
223 {
224 std::cerr << "could not open file " << lidPath.c_str() << "\n";
225 return PLDM_ERROR;
226 }
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500227 rc = lseek(fd, offset, SEEK_SET);
Sampa Misra69508502020-09-08 00:08:21 -0500228 if (rc == -1)
229 {
230 std::cerr << "lseek failed, ERROR=" << errno
231 << ", OFFSET=" << offset << "\n";
232 return PLDM_ERROR;
233 }
Sampa Misra69508502020-09-08 00:08:21 -0500234 rc = ::write(fd, buffer, length);
235 if (rc == -1)
236 {
237 std::cerr << "file write failed, ERROR=" << errno
238 << ", LENGTH=" << length << ", OFFSET=" << offset << "\n";
239 return PLDM_ERROR;
240 }
Pavithra Barithaya303387e2021-03-18 23:35:42 -0500241 else if (rc == static_cast<int>(length))
242 {
243 rc = PLDM_SUCCESS;
244 }
245 else if (rc < static_cast<int>(length))
246 {
247 rc = PLDM_ERROR;
248 }
Sampa Misra69508502020-09-08 00:08:21 -0500249 close(fd);
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500250
251 if (lidType == PLDM_FILE_TYPE_LID_MARKER)
252 {
253 markerLIDremainingSize -= length;
254 if (markerLIDremainingSize == 0)
255 {
256 pldm::responder::oem_ibm_platform::Handler*
257 oemIbmPlatformHandler = dynamic_cast<
258 pldm::responder::oem_ibm_platform::Handler*>(
259 oemPlatformHandler);
260 auto sensorId =
261 oemIbmPlatformHandler->codeUpdate->getMarkerLidSensor();
262 using namespace pldm::responder::oem_ibm_platform;
263 oemIbmPlatformHandler->sendStateSensorEvent(
264 sensorId, PLDM_STATE_SENSOR_STATE, 0, VALID, VALID);
265 // validate api
266 rc = PLDM_SUCCESS;
267 }
268 }
269 else if (codeUpdateInProgress)
270 {
271 rc = processCodeUpdateLid(lidPath);
272 }
273
Sampa Misra69508502020-09-08 00:08:21 -0500274 return rc;
Sampa Misra18967162020-01-14 02:31:41 -0600275 }
276
Sampa Misra69508502020-09-08 00:08:21 -0500277 virtual int read(uint32_t offset, uint32_t& length, Response& response,
278 oem_platform::Handler* oemPlatformHandler)
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600279 {
Sampa Misra69508502020-09-08 00:08:21 -0500280 if (constructLIDPath(oemPlatformHandler))
281 {
282 return readFile(lidPath, offset, length, response);
283 }
284 return PLDM_ERROR;
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600285 }
286
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600287 virtual int fileAck(uint8_t /*fileStatus*/)
288 {
289 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
290 }
291
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500292 virtual int newFileAvailable(uint64_t length)
Sampa Misra18967162020-01-14 02:31:41 -0600293
294 {
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500295 if (lidType == PLDM_FILE_TYPE_LID_MARKER)
296 {
297 markerLIDremainingSize = length;
298 return PLDM_SUCCESS;
299 }
Sampa Misra18967162020-01-14 02:31:41 -0600300 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
301 }
302
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600303 /** @brief LidHandler destructor
304 */
305 ~LidHandler()
George Liu6492f522020-06-16 10:34:05 +0800306 {}
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600307
308 protected:
309 std::string lidPath;
Sampa Misra69508502020-09-08 00:08:21 -0500310 std::string sideToRead;
311 bool isPatchDir;
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500312 static inline MarkerLIDremainingSize markerLIDremainingSize;
313 uint8_t lidType;
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600314};
315
316} // namespace responder
317} // namespace pldm