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/oem/ibm/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}, FILE_HANDLE={FILE_HANDLE}", 94 "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE", 95 fileHandle); 96 return PLDM_DATA_OUT_OF_RANGE; 97 } 98 if (offset + length > fileSize) 99 { 100 length = fileSize - offset; 101 } 102 } 103 104 int flags{}; 105 if (upstream) 106 { 107 flags = O_RDONLY; 108 } 109 else if (fileExists) 110 { 111 flags = O_RDWR; 112 } 113 else 114 { 115 flags = O_WRONLY; 116 } 117 int file = open(path.string().c_str(), flags); 118 if (file == -1) 119 { 120 error("File does not exist, PATH = {FILE_PATH}", "FILE_PATH", 121 path.string()); 122 return PLDM_ERROR; 123 } 124 utils::CustomFD fd(file); 125 126 return transferFileData(fd(), upstream, offset, length, address); 127 } 128 129 std::unique_ptr<FileHandler> getHandlerByType(uint16_t fileType, 130 uint32_t fileHandle) 131 { 132 switch (fileType) 133 { 134 case PLDM_FILE_TYPE_PEL: 135 { 136 return std::make_unique<PelHandler>(fileHandle); 137 } 138 case PLDM_FILE_TYPE_LID_PERM: 139 { 140 return std::make_unique<LidHandler>(fileHandle, true); 141 } 142 case PLDM_FILE_TYPE_LID_TEMP: 143 { 144 return std::make_unique<LidHandler>(fileHandle, false); 145 } 146 case PLDM_FILE_TYPE_LID_MARKER: 147 { 148 return std::make_unique<LidHandler>(fileHandle, false, 149 PLDM_FILE_TYPE_LID_MARKER); 150 } 151 case PLDM_FILE_TYPE_DUMP: 152 case PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS: 153 case PLDM_FILE_TYPE_RESOURCE_DUMP: 154 { 155 return std::make_unique<DumpHandler>(fileHandle, fileType); 156 } 157 case PLDM_FILE_TYPE_CERT_SIGNING_REQUEST: 158 case PLDM_FILE_TYPE_SIGNED_CERT: 159 case PLDM_FILE_TYPE_ROOT_CERT: 160 { 161 return std::make_unique<CertHandler>(fileHandle, fileType); 162 } 163 case PLDM_FILE_TYPE_PROGRESS_SRC: 164 { 165 return std::make_unique<ProgressCodeHandler>(fileHandle); 166 } 167 case PLDM_FILE_TYPE_LID_RUNNING: 168 { 169 return std::make_unique<LidHandler>(fileHandle, false, 170 PLDM_FILE_TYPE_LID_RUNNING); 171 } 172 case PLDM_FILE_TYPE_PSPD_VPD_PDD_KEYWORD: 173 { 174 return std::make_unique<keywordHandler>(fileHandle, fileType); 175 } 176 default: 177 { 178 throw InternalFailure(); 179 break; 180 } 181 } 182 return nullptr; 183 } 184 185 int FileHandler::readFile(const std::string& filePath, uint32_t offset, 186 uint32_t& length, Response& response) 187 { 188 if (!fs::exists(filePath)) 189 { 190 error("File does not exist, HANDLE={FILE_HANDLE} PATH={FILE_PATH}", 191 "FILE_HANDLE", fileHandle, "FILE_PATH", filePath.c_str()); 192 return PLDM_INVALID_FILE_HANDLE; 193 } 194 195 size_t fileSize = fs::file_size(filePath); 196 if (offset >= fileSize) 197 { 198 error( 199 "Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE} FILE_HANDLE={FILE_HANDLE}", 200 "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE", fileHandle); 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