1 #include "file_io_by_type.hpp" 2 3 #include "common/utils.hpp" 4 #include "file_io_type_cert.hpp" 5 #include "file_io_type_dump.hpp" 6 #include "file_io_type_lid.hpp" 7 #include "file_io_type_pel.hpp" 8 #include "file_io_type_progress_src.hpp" 9 #include "file_io_type_vpd.hpp" 10 #include "xyz/openbmc_project/Common/error.hpp" 11 12 #include <libpldm/base.h> 13 #include <libpldm/file_io.h> 14 #include <stdint.h> 15 #include <unistd.h> 16 17 #include <phosphor-logging/lg2.hpp> 18 #include <xyz/openbmc_project/Logging/Entry/server.hpp> 19 20 #include <exception> 21 #include <filesystem> 22 #include <fstream> 23 #include <iostream> 24 #include <vector> 25 26 PHOSPHOR_LOG2_USING; 27 28 namespace pldm 29 { 30 namespace responder 31 { 32 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 33 34 int FileHandler::transferFileData(int32_t fd, bool upstream, uint32_t offset, 35 uint32_t& length, uint64_t address) 36 { 37 dma::DMA xdmaInterface; 38 while (length > dma::maxSize) 39 { 40 auto rc = xdmaInterface.transferDataHost(fd, offset, dma::maxSize, 41 address, upstream); 42 if (rc < 0) 43 { 44 return PLDM_ERROR; 45 } 46 offset += dma::maxSize; 47 length -= dma::maxSize; 48 address += dma::maxSize; 49 } 50 auto rc = xdmaInterface.transferDataHost(fd, offset, length, address, 51 upstream); 52 return rc < 0 ? PLDM_ERROR : PLDM_SUCCESS; 53 } 54 55 int FileHandler::transferFileDataToSocket(int32_t fd, uint32_t& length, 56 uint64_t address) 57 { 58 dma::DMA xdmaInterface; 59 while (length > dma::maxSize) 60 { 61 auto rc = xdmaInterface.transferHostDataToSocket(fd, dma::maxSize, 62 address); 63 if (rc < 0) 64 { 65 return PLDM_ERROR; 66 } 67 length -= dma::maxSize; 68 address += dma::maxSize; 69 } 70 auto rc = xdmaInterface.transferHostDataToSocket(fd, length, address); 71 return rc < 0 ? PLDM_ERROR : PLDM_SUCCESS; 72 } 73 74 int FileHandler::transferFileData(const fs::path& path, bool upstream, 75 uint32_t offset, uint32_t& length, 76 uint64_t address) 77 { 78 bool fileExists = false; 79 if (upstream) 80 { 81 fileExists = fs::exists(path); 82 if (!fileExists) 83 { 84 error("File does not exist. PATH={FILE_PATH}", "FILE_PATH", 85 path.c_str()); 86 return PLDM_INVALID_FILE_HANDLE; 87 } 88 89 size_t fileSize = fs::file_size(path); 90 if (offset >= fileSize) 91 { 92 error( 93 "Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}", 94 "OFFSET", offset, "FILE_SIZE", fileSize); 95 return PLDM_DATA_OUT_OF_RANGE; 96 } 97 if (offset + length > fileSize) 98 { 99 length = fileSize - offset; 100 } 101 } 102 103 int flags{}; 104 if (upstream) 105 { 106 flags = O_RDONLY; 107 } 108 else if (fileExists) 109 { 110 flags = O_RDWR; 111 } 112 else 113 { 114 flags = O_WRONLY; 115 } 116 int file = open(path.string().c_str(), flags); 117 if (file == -1) 118 { 119 error("File does not exist, PATH = {FILE_PATH}", "FILE_PATH", 120 path.string()); 121 return PLDM_ERROR; 122 } 123 utils::CustomFD fd(file); 124 125 return transferFileData(fd(), upstream, offset, length, address); 126 } 127 128 std::unique_ptr<FileHandler> getHandlerByType(uint16_t fileType, 129 uint32_t fileHandle) 130 { 131 switch (fileType) 132 { 133 case PLDM_FILE_TYPE_PEL: 134 { 135 return std::make_unique<PelHandler>(fileHandle); 136 } 137 case PLDM_FILE_TYPE_LID_PERM: 138 { 139 return std::make_unique<LidHandler>(fileHandle, true); 140 } 141 case PLDM_FILE_TYPE_LID_TEMP: 142 { 143 return std::make_unique<LidHandler>(fileHandle, false); 144 } 145 case PLDM_FILE_TYPE_LID_MARKER: 146 { 147 return std::make_unique<LidHandler>(fileHandle, false, 148 PLDM_FILE_TYPE_LID_MARKER); 149 } 150 case PLDM_FILE_TYPE_DUMP: 151 case PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS: 152 case PLDM_FILE_TYPE_RESOURCE_DUMP: 153 { 154 return std::make_unique<DumpHandler>(fileHandle, fileType); 155 } 156 case PLDM_FILE_TYPE_CERT_SIGNING_REQUEST: 157 case PLDM_FILE_TYPE_SIGNED_CERT: 158 case PLDM_FILE_TYPE_ROOT_CERT: 159 { 160 return std::make_unique<CertHandler>(fileHandle, fileType); 161 } 162 case PLDM_FILE_TYPE_PROGRESS_SRC: 163 { 164 return std::make_unique<ProgressCodeHandler>(fileHandle); 165 } 166 case PLDM_FILE_TYPE_LID_RUNNING: 167 { 168 return std::make_unique<LidHandler>(fileHandle, false, 169 PLDM_FILE_TYPE_LID_RUNNING); 170 } 171 case PLDM_FILE_TYPE_PSPD_VPD_PDD_KEYWORD: 172 { 173 return std::make_unique<keywordHandler>(fileHandle, fileType); 174 } 175 default: 176 { 177 throw InternalFailure(); 178 break; 179 } 180 } 181 return nullptr; 182 } 183 184 int FileHandler::readFile(const std::string& filePath, uint32_t offset, 185 uint32_t& length, Response& response) 186 { 187 if (!fs::exists(filePath)) 188 { 189 error("File does not exist, HANDLE={FILE_HANDLE} PATH={FILE_PATH}", 190 "FILE_HANDLE", fileHandle, "FILE_PATH", filePath.c_str()); 191 return PLDM_INVALID_FILE_HANDLE; 192 } 193 194 size_t fileSize = fs::file_size(filePath); 195 if (offset >= fileSize) 196 { 197 error("Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}", 198 "OFFSET", offset, "FILE_SIZE", fileSize); 199 return PLDM_DATA_OUT_OF_RANGE; 200 } 201 202 if (offset + length > fileSize) 203 { 204 length = fileSize - offset; 205 } 206 207 size_t currSize = response.size(); 208 response.resize(currSize + length); 209 auto filePos = reinterpret_cast<char*>(response.data()); 210 filePos += currSize; 211 std::ifstream stream(filePath, std::ios::in | std::ios::binary); 212 if (stream) 213 { 214 stream.seekg(offset); 215 stream.read(filePos, length); 216 return PLDM_SUCCESS; 217 } 218 error("Unable to read file, FILE={FILE_PATH}", "FILE_PATH", 219 filePath.c_str()); 220 return PLDM_ERROR; 221 } 222 223 } // namespace responder 224 } // namespace pldm 225