1 #pragma once 2 3 #include "handler.hpp" 4 5 #include <stdint.h> 6 #include <unistd.h> 7 8 #include <filesystem> 9 #include <vector> 10 11 #include "libpldm/base.h" 12 #include "oem/ibm/libpldm/file_io.h" 13 14 namespace pldm 15 { 16 namespace responder 17 { 18 namespace dma 19 { 20 21 // The minimum data size of dma transfer in bytes 22 constexpr uint32_t minSize = 16; 23 24 // 16MB - 4096B (16773120 bytes) is the maximum data size of DMA transfer 25 constexpr size_t maxSize = (16 * 1024 * 1024) - 4096; 26 27 namespace fs = std::filesystem; 28 29 /** 30 * @class DMA 31 * 32 * Expose API to initiate transfer of data by DMA 33 * 34 * This class only exposes the public API transferDataHost to transfer data 35 * between BMC and host using DMA. This allows for mocking the transferDataHost 36 * for unit testing purposes. 37 */ 38 class DMA 39 { 40 public: 41 /** @brief API to transfer data between BMC and host using DMA 42 * 43 * @param[in] path - pathname of the file to transfer data from or to 44 * @param[in] offset - offset in the file 45 * @param[in] length - length of the data to transfer 46 * @param[in] address - DMA address on the host 47 * @param[in] upstream - indicates direction of the transfer; true indicates 48 * transfer to the host 49 * 50 * @return returns 0 on success, negative errno on failure 51 */ 52 int transferDataHost(const fs::path& path, uint32_t offset, uint32_t length, 53 uint64_t address, bool upstream); 54 }; 55 56 /** @brief Transfer the data between BMC and host using DMA. 57 * 58 * There is a max size for each DMA operation, transferAll API abstracts this 59 * and the requested length is broken down into multiple DMA operations if the 60 * length exceed max size. 61 * 62 * @tparam[in] T - DMA interface type 63 * @param[in] intf - interface passed to invoke DMA transfer 64 * @param[in] command - PLDM command 65 * @param[in] path - pathname of the file to transfer data from or to 66 * @param[in] offset - offset in the file 67 * @param[in] length - length of the data to transfer 68 * @param[in] address - DMA address on the host 69 * @param[in] upstream - indicates direction of the transfer; true indicates 70 * transfer to the host 71 * @param[in] instanceId - Message's instance id 72 * @return PLDM response message 73 */ 74 75 template <class DMAInterface> 76 Response transferAll(DMAInterface* intf, uint8_t command, fs::path& path, 77 uint32_t offset, uint32_t length, uint64_t address, 78 bool upstream, uint8_t instanceId) 79 { 80 uint32_t origLength = length; 81 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); 82 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 83 84 while (length > dma::maxSize) 85 { 86 auto rc = intf->transferDataHost(path, offset, dma::maxSize, address, 87 upstream); 88 if (rc < 0) 89 { 90 encode_rw_file_memory_resp(instanceId, command, PLDM_ERROR, 0, 91 responsePtr); 92 return response; 93 } 94 95 offset += dma::maxSize; 96 length -= dma::maxSize; 97 address += dma::maxSize; 98 } 99 100 auto rc = intf->transferDataHost(path, offset, length, address, upstream); 101 if (rc < 0) 102 { 103 encode_rw_file_memory_resp(instanceId, command, PLDM_ERROR, 0, 104 responsePtr); 105 return response; 106 } 107 108 encode_rw_file_memory_resp(instanceId, command, PLDM_SUCCESS, origLength, 109 responsePtr); 110 return response; 111 } 112 113 } // namespace dma 114 115 namespace oem_ibm 116 { 117 118 class Handler : public CmdHandler 119 { 120 public: 121 Handler() 122 { 123 handlers.emplace(PLDM_READ_FILE_INTO_MEMORY, 124 [this](const pldm_msg* request, size_t payloadLength) { 125 return this->readFileIntoMemory(request, 126 payloadLength); 127 }); 128 handlers.emplace(PLDM_WRITE_FILE_FROM_MEMORY, 129 [this](const pldm_msg* request, size_t payloadLength) { 130 return this->writeFileFromMemory(request, 131 payloadLength); 132 }); 133 handlers.emplace(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, 134 [this](const pldm_msg* request, size_t payloadLength) { 135 return this->writeFileByTypeFromMemory( 136 request, payloadLength); 137 }); 138 handlers.emplace(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, 139 [this](const pldm_msg* request, size_t payloadLength) { 140 return this->readFileByTypeIntoMemory( 141 request, payloadLength); 142 }); 143 handlers.emplace(PLDM_READ_FILE_BY_TYPE, [this](const pldm_msg* request, 144 size_t payloadLength) { 145 return this->readFileByType(request, payloadLength); 146 }); 147 handlers.emplace(PLDM_GET_FILE_TABLE, 148 [this](const pldm_msg* request, size_t payloadLength) { 149 return this->getFileTable(request, payloadLength); 150 }); 151 handlers.emplace(PLDM_READ_FILE, 152 [this](const pldm_msg* request, size_t payloadLength) { 153 return this->readFile(request, payloadLength); 154 }); 155 handlers.emplace(PLDM_WRITE_FILE, 156 [this](const pldm_msg* request, size_t payloadLength) { 157 return this->writeFile(request, payloadLength); 158 }); 159 } 160 161 /** @brief Handler for readFileIntoMemory command 162 * 163 * @param[in] request - pointer to PLDM request payload 164 * @param[in] payloadLength - length of the message 165 * 166 * @return PLDM response message 167 */ 168 Response readFileIntoMemory(const pldm_msg* request, size_t payloadLength); 169 170 /** @brief Handler for writeFileIntoMemory command 171 * 172 * @param[in] request - pointer to PLDM request payload 173 * @param[in] payloadLength - length of the message 174 * 175 * @return PLDM response message 176 */ 177 Response writeFileFromMemory(const pldm_msg* request, size_t payloadLength); 178 179 /** @brief Handler for writeFileByTypeFromMemory command 180 * 181 * @param[in] request - pointer to PLDM request payload 182 * @param[in] payloadLength - length of the message 183 * 184 * @return PLDM response message 185 */ 186 187 Response writeFileByTypeFromMemory(const pldm_msg* request, 188 size_t payloadLength); 189 190 /** @brief Handler for readFileByTypeIntoMemory command 191 * 192 * @param[in] request - pointer to PLDM request payload 193 * @param[in] payloadLength - length of the message 194 * 195 * @return PLDM response message 196 */ 197 Response readFileByTypeIntoMemory(const pldm_msg* request, 198 size_t payloadLength); 199 200 /** @brief Handler for readFileByType command 201 * 202 * @param[in] request - pointer to PLDM request payload 203 * @param[in] payloadLength - length of the message 204 * 205 * @return PLDM response message 206 */ 207 Response readFileByType(const pldm_msg* request, size_t payloadLength); 208 209 /** @brief Handler for GetFileTable command 210 * 211 * @param[in] request - pointer to PLDM request payload 212 * @param[in] payloadLength - length of the message payload 213 * 214 * @return PLDM response message 215 */ 216 Response getFileTable(const pldm_msg* request, size_t payloadLength); 217 218 /** @brief Handler for readFile command 219 * 220 * @param[in] request - PLDM request msg 221 * @param[in] payloadLength - length of the message payload 222 * 223 * @return PLDM response message 224 */ 225 Response readFile(const pldm_msg* request, size_t payloadLength); 226 227 /** @brief Handler for writeFile command 228 * 229 * @param[in] request - PLDM request msg 230 * @param[in] payloadLength - length of the message payload 231 * 232 * @return PLDM response message 233 */ 234 Response writeFile(const pldm_msg* request, size_t payloadLength); 235 }; 236 237 } // namespace oem_ibm 238 } // namespace responder 239 } // namespace pldm 240