1 #include "config.h" 2 3 #include "file_io_by_type.hpp" 4 5 #include "libpldm/base.h" 6 #include "oem/ibm/libpldm/file_io.h" 7 8 #include "common/utils.hpp" 9 #include "file_io_type_cert.hpp" 10 #include "file_io_type_dump.hpp" 11 #include "file_io_type_lid.hpp" 12 #include "file_io_type_pel.hpp" 13 #include "file_io_type_progress_src.hpp" 14 #include "xyz/openbmc_project/Common/error.hpp" 15 16 #include <stdint.h> 17 #include <unistd.h> 18 19 #include <xyz/openbmc_project/Logging/Entry/server.hpp> 20 21 #include <exception> 22 #include <filesystem> 23 #include <fstream> 24 #include <iostream> 25 #include <vector> 26 27 namespace pldm 28 { 29 namespace responder 30 { 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 = 51 xdmaInterface.transferDataHost(fd, offset, length, address, 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 = 62 xdmaInterface.transferHostDataToSocket(fd, dma::maxSize, 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 std::cerr << "File does not exist. PATH=" << path.c_str() << "\n"; 85 return PLDM_INVALID_FILE_HANDLE; 86 } 87 88 size_t fileSize = fs::file_size(path); 89 if (offset >= fileSize) 90 { 91 std::cerr << "Offset exceeds file size, OFFSET=" << offset 92 << " FILE_SIZE=" << fileSize << "\n"; 93 return PLDM_DATA_OUT_OF_RANGE; 94 } 95 if (offset + length > fileSize) 96 { 97 length = fileSize - offset; 98 } 99 } 100 101 int flags{}; 102 if (upstream) 103 { 104 flags = O_RDONLY; 105 } 106 else if (fileExists) 107 { 108 flags = O_RDWR; 109 } 110 else 111 { 112 flags = O_WRONLY; 113 } 114 int file = open(path.string().c_str(), flags); 115 if (file == -1) 116 { 117 std::cerr << "File does not exist, PATH = " << path.string() << "\n"; 118 ; 119 return PLDM_ERROR; 120 } 121 utils::CustomFD fd(file); 122 123 return transferFileData(fd(), upstream, offset, length, address); 124 } 125 126 std::unique_ptr<FileHandler> getHandlerByType(uint16_t fileType, 127 uint32_t fileHandle) 128 { 129 switch (fileType) 130 { 131 case PLDM_FILE_TYPE_PEL: 132 { 133 return std::make_unique<PelHandler>(fileHandle); 134 } 135 case PLDM_FILE_TYPE_LID_PERM: 136 { 137 return std::make_unique<LidHandler>(fileHandle, true); 138 } 139 case PLDM_FILE_TYPE_LID_TEMP: 140 { 141 return std::make_unique<LidHandler>(fileHandle, false); 142 } 143 case PLDM_FILE_TYPE_LID_MARKER: 144 { 145 return std::make_unique<LidHandler>(fileHandle, false, 146 PLDM_FILE_TYPE_LID_MARKER); 147 } 148 case PLDM_FILE_TYPE_DUMP: 149 case PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS: 150 case PLDM_FILE_TYPE_RESOURCE_DUMP: 151 { 152 return std::make_unique<DumpHandler>(fileHandle, fileType); 153 } 154 case PLDM_FILE_TYPE_CERT_SIGNING_REQUEST: 155 case PLDM_FILE_TYPE_SIGNED_CERT: 156 case PLDM_FILE_TYPE_ROOT_CERT: 157 { 158 return std::make_unique<CertHandler>(fileHandle, fileType); 159 } 160 case PLDM_FILE_TYPE_PROGRESS_SRC: 161 { 162 return std::make_unique<ProgressCodeHandler>(fileHandle); 163 } 164 default: 165 { 166 throw InternalFailure(); 167 break; 168 } 169 } 170 return nullptr; 171 } 172 173 int FileHandler::readFile(const std::string& filePath, uint32_t offset, 174 uint32_t& length, Response& response) 175 { 176 if (!fs::exists(filePath)) 177 { 178 std::cerr << "File does not exist, HANDLE=" << fileHandle 179 << " PATH=" << filePath.c_str() << "\n"; 180 return PLDM_INVALID_FILE_HANDLE; 181 } 182 183 size_t fileSize = fs::file_size(filePath); 184 if (offset >= fileSize) 185 { 186 std::cerr << "Offset exceeds file size, OFFSET=" << offset 187 << " FILE_SIZE=" << fileSize << "\n"; 188 return PLDM_DATA_OUT_OF_RANGE; 189 } 190 191 if (offset + length > fileSize) 192 { 193 length = fileSize - offset; 194 } 195 196 size_t currSize = response.size(); 197 response.resize(currSize + length); 198 auto filePos = reinterpret_cast<char*>(response.data()); 199 filePos += currSize; 200 std::ifstream stream(filePath, std::ios::in | std::ios::binary); 201 if (stream) 202 { 203 stream.seekg(offset); 204 stream.read(filePos, length); 205 return PLDM_SUCCESS; 206 } 207 std::cerr << "Unable to read file, FILE=" << filePath.c_str() << "\n"; 208 return PLDM_ERROR; 209 } 210 211 } // namespace responder 212 } // namespace pldm 213