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 namespace fs = std::filesystem; 17 18 using MarkerLIDremainingSize = uint64_t; 19 20 /** @class LidHandler 21 * 22 * @brief Inherits and implements FileHandler. This class is used 23 * to read/write LIDs. 24 */ 25 class LidHandler : public FileHandler 26 { 27 public: 28 /** @brief LidHandler constructor 29 */ 30 LidHandler(uint32_t fileHandle, bool permSide, uint8_t lidType = 0) : 31 FileHandler(fileHandle), lidType(lidType) 32 { 33 sideToRead = permSide ? Pside : Tside; 34 isPatchDir = false; 35 std::string dir = permSide ? LID_ALTERNATE_DIR : LID_RUNNING_DIR; 36 std::stringstream stream; 37 stream << std::hex << fileHandle; 38 auto lidName = stream.str() + ".lid"; 39 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)) 43 { 44 lidPath = patch; 45 isPatchDir = true; 46 } 47 else 48 { 49 lidPath = std::move(dir) + '/' + lidName; 50 } 51 } 52 53 /** @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) 58 { 59 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 { 99 int rc = PLDM_SUCCESS; 100 bool codeUpdateInProgress = false; 101 if (oemPlatformHandler != nullptr) 102 { 103 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler = 104 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>( 105 oemPlatformHandler); 106 codeUpdateInProgress = 107 oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress(); 108 if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER) 109 { 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 } 117 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 } 127 auto fd = open(lidPath.c_str(), flags, S_IRUSR); 128 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 136 rc = transferFileData(lidPath, false, offset, length, address); 137 if (rc != PLDM_SUCCESS) 138 { 139 std::cerr << "writeFileFromMemory failed with rc= " << rc << " \n"; 140 return rc; 141 } 142 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 } 164 return rc; 165 } 166 167 virtual int readIntoMemory(uint32_t offset, uint32_t& length, 168 uint64_t address, 169 oem_platform::Handler* oemPlatformHandler) 170 { 171 if (constructLIDPath(oemPlatformHandler)) 172 { 173 return transferFileData(lidPath, true, offset, length, address); 174 } 175 return PLDM_ERROR; 176 } 177 178 virtual int write(const char* buffer, uint32_t offset, uint32_t& length, 179 oem_platform::Handler* oemPlatformHandler) 180 { 181 int rc = PLDM_SUCCESS; 182 bool codeUpdateInProgress = false; 183 if (oemPlatformHandler != nullptr) 184 { 185 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler = 186 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>( 187 oemPlatformHandler); 188 codeUpdateInProgress = 189 oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress(); 190 if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER) 191 { 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 } 199 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 } 221 auto fd = open(lidPath.c_str(), flags, S_IRUSR); 222 if (fd == -1) 223 { 224 std::cerr << "could not open file " << lidPath.c_str() << "\n"; 225 return PLDM_ERROR; 226 } 227 rc = lseek(fd, offset, SEEK_SET); 228 if (rc == -1) 229 { 230 std::cerr << "lseek failed, ERROR=" << errno 231 << ", OFFSET=" << offset << "\n"; 232 return PLDM_ERROR; 233 } 234 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 } 241 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 } 249 close(fd); 250 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 274 return rc; 275 } 276 277 virtual int read(uint32_t offset, uint32_t& length, Response& response, 278 oem_platform::Handler* oemPlatformHandler) 279 { 280 if (constructLIDPath(oemPlatformHandler)) 281 { 282 return readFile(lidPath, offset, length, response); 283 } 284 return PLDM_ERROR; 285 } 286 287 virtual int fileAck(uint8_t /*fileStatus*/) 288 { 289 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; 290 } 291 292 virtual int newFileAvailable(uint64_t length) 293 294 { 295 if (lidType == PLDM_FILE_TYPE_LID_MARKER) 296 { 297 markerLIDremainingSize = length; 298 return PLDM_SUCCESS; 299 } 300 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; 301 } 302 303 /** @brief LidHandler destructor 304 */ 305 ~LidHandler() 306 {} 307 308 protected: 309 std::string lidPath; 310 std::string sideToRead; 311 bool isPatchDir; 312 static inline MarkerLIDremainingSize markerLIDremainingSize; 313 uint8_t lidType; 314 }; 315 316 } // namespace responder 317 } // namespace pldm 318