1 #pragma once 2 3 #include "config.h" 4 5 #include "file_io_by_type.hpp" 6 7 #include <filesystem> 8 #include <sstream> 9 #include <string> 10 11 namespace pldm 12 { 13 namespace responder 14 { 15 16 using namespace pldm::responder::dma; 17 namespace fs = std::filesystem; 18 19 using MarkerLIDremainingSize = uint64_t; 20 21 /** @class LidHandler 22 * 23 * @brief Inherits and implements FileHandler. This class is used 24 * to read/write LIDs. 25 */ 26 class LidHandler : public FileHandler 27 { 28 public: 29 /** @brief LidHandler constructor 30 */ 31 LidHandler(uint32_t fileHandle, bool permSide, uint8_t lidType = 0) : 32 FileHandler(fileHandle), lidType(lidType) 33 { 34 sideToRead = permSide ? Pside : Tside; 35 isPatchDir = false; 36 std::string dir = permSide ? LID_ALTERNATE_DIR : LID_RUNNING_DIR; 37 std::stringstream stream; 38 stream << std::hex << fileHandle; 39 auto lidName = stream.str() + ".lid"; 40 std::string patchDir = 41 permSide ? LID_ALTERNATE_PATCH_DIR : LID_RUNNING_PATCH_DIR; 42 auto patch = fs::path(patchDir) / lidName; 43 if (fs::is_regular_file(patch)) 44 { 45 lidPath = patch; 46 isPatchDir = true; 47 } 48 else 49 { 50 lidPath = std::move(dir) + '/' + lidName; 51 } 52 } 53 54 /** @brief Method to construct the LID path based on current boot side 55 * @param[in] oemPlatformHandler - OEM platform handler 56 * @return bool - true if a new path is constructed 57 */ 58 bool constructLIDPath(oem_platform::Handler* oemPlatformHandler) 59 { 60 if (oemPlatformHandler != nullptr) 61 { 62 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler = 63 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>( 64 oemPlatformHandler); 65 std::string dir = LID_ALTERNATE_DIR; 66 if (isPatchDir) 67 { 68 dir = LID_ALTERNATE_PATCH_DIR; 69 } 70 if (oemIbmPlatformHandler->codeUpdate->fetchCurrentBootSide() == 71 sideToRead) 72 { 73 if (isPatchDir) 74 { 75 dir = LID_RUNNING_PATCH_DIR; 76 } 77 else 78 { 79 dir = LID_RUNNING_DIR; 80 } 81 } 82 else if (oemIbmPlatformHandler->codeUpdate 83 ->isCodeUpdateInProgress()) 84 { 85 return false; 86 } 87 88 std::stringstream stream; 89 stream << std::hex << fileHandle; 90 auto lidName = stream.str() + ".lid"; 91 lidPath = std::move(dir) + '/' + lidName; 92 } 93 return true; 94 } 95 96 virtual int writeFromMemory(uint32_t offset, uint32_t length, 97 uint64_t address, 98 oem_platform::Handler* oemPlatformHandler) 99 { 100 int rc = PLDM_SUCCESS; 101 bool codeUpdateInProgress = false; 102 if (oemPlatformHandler != nullptr) 103 { 104 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler = 105 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>( 106 oemPlatformHandler); 107 codeUpdateInProgress = 108 oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress(); 109 if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER) 110 { 111 std::string dir = LID_STAGING_DIR; 112 std::stringstream stream; 113 stream << std::hex << fileHandle; 114 auto lidName = stream.str() + ".lid"; 115 lidPath = std::move(dir) + '/' + lidName; 116 } 117 } 118 bool fileExists = fs::exists(lidPath); 119 int flags{}; 120 if (fileExists) 121 { 122 flags = O_RDWR; 123 } 124 else 125 { 126 flags = O_WRONLY | O_CREAT | O_TRUNC | O_SYNC; 127 } 128 auto fd = open(lidPath.c_str(), flags, S_IRUSR); 129 if (fd == -1) 130 { 131 std::cerr << "Could not open file for writing " << lidPath.c_str() 132 << "\n"; 133 return PLDM_ERROR; 134 } 135 close(fd); 136 137 rc = transferFileData(lidPath, false, offset, length, address); 138 if (rc != PLDM_SUCCESS) 139 { 140 std::cerr << "writeFileFromMemory failed with rc= " << rc << " \n"; 141 return rc; 142 } 143 if (lidType == PLDM_FILE_TYPE_LID_MARKER) 144 { 145 markerLIDremainingSize -= length; 146 if (markerLIDremainingSize == 0) 147 { 148 pldm::responder::oem_ibm_platform::Handler* 149 oemIbmPlatformHandler = dynamic_cast< 150 pldm::responder::oem_ibm_platform::Handler*>( 151 oemPlatformHandler); 152 auto sensorId = 153 oemIbmPlatformHandler->codeUpdate->getMarkerLidSensor(); 154 using namespace pldm::responder::oem_ibm_platform; 155 oemIbmPlatformHandler->sendStateSensorEvent( 156 sensorId, PLDM_STATE_SENSOR_STATE, 0, VALID, VALID); 157 // rc = validate api; 158 rc = PLDM_SUCCESS; 159 } 160 } 161 else if (codeUpdateInProgress) 162 { 163 rc = processCodeUpdateLid(lidPath); 164 } 165 return rc; 166 } 167 168 virtual int readIntoMemory(uint32_t offset, uint32_t& length, 169 uint64_t address, 170 oem_platform::Handler* oemPlatformHandler) 171 { 172 if (constructLIDPath(oemPlatformHandler)) 173 { 174 return transferFileData(lidPath, true, offset, length, address); 175 } 176 return PLDM_ERROR; 177 } 178 179 virtual int write(const char* buffer, uint32_t offset, uint32_t& length, 180 oem_platform::Handler* oemPlatformHandler) 181 { 182 int rc = PLDM_SUCCESS; 183 bool codeUpdateInProgress = false; 184 if (oemPlatformHandler != nullptr) 185 { 186 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler = 187 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>( 188 oemPlatformHandler); 189 codeUpdateInProgress = 190 oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress(); 191 if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER) 192 { 193 std::string dir = LID_STAGING_DIR; 194 std::stringstream stream; 195 stream << std::hex << fileHandle; 196 auto lidName = stream.str() + ".lid"; 197 lidPath = std::move(dir) + '/' + lidName; 198 } 199 } 200 bool fileExists = fs::exists(lidPath); 201 int flags{}; 202 if (fileExists) 203 { 204 flags = O_RDWR; 205 size_t fileSize = fs::file_size(lidPath); 206 if (offset > fileSize) 207 { 208 std::cerr << "Offset exceeds file size, OFFSET=" << offset 209 << " FILE_SIZE=" << fileSize << "\n"; 210 return PLDM_DATA_OUT_OF_RANGE; 211 } 212 } 213 else 214 { 215 flags = O_WRONLY | O_CREAT | O_TRUNC | O_SYNC; 216 if (offset > 0) 217 { 218 std::cerr << "Offset is non zero in a new file \n"; 219 return PLDM_DATA_OUT_OF_RANGE; 220 } 221 } 222 auto fd = open(lidPath.c_str(), flags, S_IRUSR); 223 if (fd == -1) 224 { 225 std::cerr << "could not open file " << lidPath.c_str() << "\n"; 226 return PLDM_ERROR; 227 } 228 rc = lseek(fd, offset, SEEK_SET); 229 if (rc == -1) 230 { 231 std::cerr << "lseek failed, ERROR=" << errno 232 << ", OFFSET=" << offset << "\n"; 233 return PLDM_ERROR; 234 } 235 rc = ::write(fd, buffer, length); 236 if (rc == -1) 237 { 238 std::cerr << "file write failed, ERROR=" << errno 239 << ", LENGTH=" << length << ", OFFSET=" << offset << "\n"; 240 return PLDM_ERROR; 241 } 242 else if (rc == static_cast<int>(length)) 243 { 244 rc = PLDM_SUCCESS; 245 } 246 else if (rc < static_cast<int>(length)) 247 { 248 rc = PLDM_ERROR; 249 } 250 close(fd); 251 252 if (lidType == PLDM_FILE_TYPE_LID_MARKER) 253 { 254 markerLIDremainingSize -= length; 255 if (markerLIDremainingSize == 0) 256 { 257 pldm::responder::oem_ibm_platform::Handler* 258 oemIbmPlatformHandler = dynamic_cast< 259 pldm::responder::oem_ibm_platform::Handler*>( 260 oemPlatformHandler); 261 auto sensorId = 262 oemIbmPlatformHandler->codeUpdate->getMarkerLidSensor(); 263 using namespace pldm::responder::oem_ibm_platform; 264 oemIbmPlatformHandler->sendStateSensorEvent( 265 sensorId, PLDM_STATE_SENSOR_STATE, 0, VALID, VALID); 266 // validate api 267 rc = PLDM_SUCCESS; 268 } 269 } 270 else if (codeUpdateInProgress) 271 { 272 rc = processCodeUpdateLid(lidPath); 273 } 274 275 return rc; 276 } 277 278 virtual int read(uint32_t offset, uint32_t& length, Response& response, 279 oem_platform::Handler* oemPlatformHandler) 280 { 281 if (constructLIDPath(oemPlatformHandler)) 282 { 283 return readFile(lidPath, offset, length, response); 284 } 285 return PLDM_ERROR; 286 } 287 288 virtual int fileAck(uint8_t /*fileStatus*/) 289 { 290 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; 291 } 292 293 virtual int newFileAvailable(uint64_t length) 294 295 { 296 if (lidType == PLDM_FILE_TYPE_LID_MARKER) 297 { 298 markerLIDremainingSize = length; 299 return PLDM_SUCCESS; 300 } 301 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; 302 } 303 304 /** @brief LidHandler destructor 305 */ 306 ~LidHandler() 307 {} 308 309 protected: 310 std::string lidPath; 311 std::string sideToRead; 312 bool isPatchDir; 313 static inline MarkerLIDremainingSize markerLIDremainingSize; 314 uint8_t lidType; 315 }; 316 317 } // namespace responder 318 } // namespace pldm 319