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 * @param[in] instanceId - Message's instance id 81 * @return PLDM response message 82 */ 83 84 template <class DMAInterface> 85 Response transferAll(DMAInterface* intf, uint8_t command, fs::path& path, 86 uint32_t offset, uint32_t length, uint64_t address, 87 bool upstream, uint8_t instanceId) 88 { 89 uint32_t origLength = length; 90 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); 91 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 92 93 while (length > dma::maxSize) 94 { 95 auto rc = intf->transferDataHost(path, offset, dma::maxSize, address, 96 upstream); 97 if (rc < 0) 98 { 99 encode_rw_file_memory_resp(instanceId, command, PLDM_ERROR, 0, 100 responsePtr); 101 return response; 102 } 103 104 offset += dma::maxSize; 105 length -= dma::maxSize; 106 address += dma::maxSize; 107 } 108 109 auto rc = intf->transferDataHost(path, offset, length, address, upstream); 110 if (rc < 0) 111 { 112 encode_rw_file_memory_resp(instanceId, command, PLDM_ERROR, 0, 113 responsePtr); 114 return response; 115 } 116 117 encode_rw_file_memory_resp(instanceId, command, PLDM_SUCCESS, origLength, 118 responsePtr); 119 return response; 120 } 121 122 } // namespace dma 123 124 /** @brief Handler for readFileIntoMemory command 125 * 126 * @param[in] request - pointer to PLDM request payload 127 * @param[in] payloadLength - length of the message 128 * 129 * @return PLDM response message 130 */ 131 Response readFileIntoMemory(const pldm_msg* request, size_t payloadLength); 132 133 /** @brief Handler for writeFileIntoMemory command 134 * 135 * @param[in] request - pointer to PLDM request payload 136 * @param[in] payloadLength - length of the message 137 * 138 * @return PLDM response message 139 */ 140 Response writeFileFromMemory(const pldm_msg* request, size_t payloadLength); 141 142 /** @brief Handler for GetFileTable command 143 * 144 * @param[in] request - pointer to PLDM request payload 145 * @param[in] payloadLength - length of the message payload 146 * 147 * @return PLDM response message 148 */ 149 Response getFileTable(const pldm_msg* request, size_t payloadLength); 150 } // namespace responder 151 } // namespace pldm 152