1 #pragma once 2 3 #include <stdint.h> 4 #include <unistd.h> 5 6 #include <filesystem> 7 #include <vector> 8 9 #include "libpldm/base.h" 10 #include "oem/ibm/libpldm/file_io.h" 11 12 namespace pldm 13 { 14 15 namespace responder 16 { 17 18 namespace oem_ibm 19 { 20 /** @brief Register handlers for command from the platform spec 21 */ 22 void registerHandlers(); 23 } // namespace oem_ibm 24 25 using Response = std::vector<uint8_t>; 26 27 namespace dma 28 { 29 30 // The minimum data size of dma transfer in bytes 31 constexpr uint32_t minSize = 16; 32 33 // 16MB - 4096B (16773120 bytes) is the maximum data size of DMA transfer 34 constexpr size_t maxSize = (16 * 1024 * 1024) - 4096; 35 36 namespace fs = std::filesystem; 37 38 /** 39 * @class DMA 40 * 41 * Expose API to initiate transfer of data by DMA 42 * 43 * This class only exposes the public API transferDataHost to transfer data 44 * between BMC and host using DMA. This allows for mocking the transferDataHost 45 * for unit testing purposes. 46 */ 47 class DMA 48 { 49 public: 50 /** @brief API to transfer data between BMC and host using DMA 51 * 52 * @param[in] path - pathname of the file to transfer data from or to 53 * @param[in] offset - offset in the file 54 * @param[in] length - length of the data to transfer 55 * @param[in] address - DMA address on the host 56 * @param[in] upstream - indicates direction of the transfer; true indicates 57 * transfer to the host 58 * 59 * @return returns 0 on success, negative errno on failure 60 */ 61 int transferDataHost(const fs::path& path, uint32_t offset, uint32_t length, 62 uint64_t address, bool upstream); 63 }; 64 65 /** @brief Transfer the data between BMC and host using DMA. 66 * 67 * There is a max size for each DMA operation, transferAll API abstracts this 68 * and the requested length is broken down into multiple DMA operations if the 69 * length exceed max size. 70 * 71 * @tparam[in] T - DMA interface type 72 * @param[in] intf - interface passed to invoke DMA transfer 73 * @param[in] command - PLDM command 74 * @param[in] path - pathname of the file to transfer data from or to 75 * @param[in] offset - offset in the file 76 * @param[in] length - length of the data to transfer 77 * @param[in] address - DMA address on the host 78 * @param[in] upstream - indicates direction of the transfer; true indicates 79 * transfer to the host 80 * @return PLDM response message 81 */ 82 83 template <class DMAInterface> 84 Response transferAll(DMAInterface* intf, uint8_t command, fs::path& path, 85 uint32_t offset, uint32_t length, uint64_t address, 86 bool upstream) 87 { 88 uint32_t origLength = length; 89 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); 90 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 91 92 while (length > dma::maxSize) 93 { 94 auto rc = intf->transferDataHost(path, offset, dma::maxSize, address, 95 upstream); 96 if (rc < 0) 97 { 98 encode_rw_file_memory_resp(0, command, PLDM_ERROR, 0, responsePtr); 99 return response; 100 } 101 102 offset += dma::maxSize; 103 length -= dma::maxSize; 104 address += dma::maxSize; 105 } 106 107 auto rc = intf->transferDataHost(path, offset, length, address, upstream); 108 if (rc < 0) 109 { 110 encode_rw_file_memory_resp(0, command, PLDM_ERROR, 0, responsePtr); 111 return response; 112 } 113 114 encode_rw_file_memory_resp(0, command, PLDM_SUCCESS, origLength, 115 responsePtr); 116 return response; 117 } 118 119 } // namespace dma 120 121 /** @brief Handler for readFileIntoMemory command 122 * 123 * @param[in] request - pointer to PLDM request payload 124 * @param[in] payloadLength - length of the message 125 * 126 * @return PLDM response message 127 */ 128 Response readFileIntoMemory(const pldm_msg* request, size_t payloadLength); 129 130 /** @brief Handler for writeFileIntoMemory command 131 * 132 * @param[in] request - pointer to PLDM request payload 133 * @param[in] payloadLength - length of the message 134 * 135 * @return PLDM response message 136 */ 137 Response writeFileFromMemory(const pldm_msg* request, size_t payloadLength); 138 139 /** @brief Handler for GetFileTable command 140 * 141 * @param[in] request - pointer to PLDM request payload 142 * @param[in] payloadLength - length of the message payload 143 * 144 * @return PLDM response message 145 */ 146 Response getFileTable(const pldm_msg* request, size_t payloadLength); 147 } // namespace responder 148 } // namespace pldm 149