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