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