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