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