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