blob: 852f5deb13ed05a63d69295b72ff2da3797d5faa [file] [log] [blame]
Tom Josephf8329ac2019-04-11 22:13:22 +05301#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
11namespace pldm
12{
13
14namespace responder
15{
16
Tom Joseph4e48b442019-06-04 09:23:44 +053017using Response = std::vector<uint8_t>;
18
Tom Josephf8329ac2019-04-11 22:13:22 +053019namespace utils
20{
21
22/** @struct CustomFD
23 *
24 * RAII wrapper for file descriptor.
25 */
26struct CustomFD
27{
28 CustomFD(const CustomFD&) = delete;
29 CustomFD& operator=(const CustomFD&) = delete;
30 CustomFD(CustomFD&&) = delete;
31 CustomFD& operator=(CustomFD&&) = delete;
32
33 CustomFD(int fd) : fd(fd)
34 {
35 }
36
37 ~CustomFD()
38 {
39 if (fd >= 0)
40 {
41 close(fd);
42 }
43 }
44
45 int operator()() const
46 {
47 return fd;
48 }
49
50 private:
51 int fd = -1;
52};
53
54} // namespace utils
55
56namespace dma
57{
58
Tom Josephf8329ac2019-04-11 22:13:22 +053059// The minimum data size of dma transfer in bytes
60constexpr uint32_t minSize = 16;
61
62// 16MB - 4096B (16773120 bytes) is the maximum data size of DMA transfer
63constexpr size_t maxSize = (16 * 1024 * 1024) - 4096;
64
Tom Joseph55306762019-05-02 09:11:26 +053065namespace fs = std::filesystem;
66
67/**
68 * @class DMA
Tom Josephf8329ac2019-04-11 22:13:22 +053069 *
Tom Joseph55306762019-05-02 09:11:26 +053070 * Expose API to initiate transfer of data by DMA
Eddie James3b02e272019-04-22 20:13:55 +000071 *
Tom Joseph55306762019-05-02 09:11:26 +053072 * This class only exposes the public API transferDataHost to transfer data
73 * between BMC and host using DMA. This allows for mocking the transferDataHost
74 * for unit testing purposes.
Tom Josephf8329ac2019-04-11 22:13:22 +053075 */
Tom Joseph55306762019-05-02 09:11:26 +053076class DMA
77{
78 public:
79 /** @brief API to transfer data between BMC and host using DMA
80 *
81 * @param[in] path - pathname of the file to transfer data from or to
82 * @param[in] offset - offset in the file
83 * @param[in] length - length of the data to transfer
84 * @param[in] address - DMA address on the host
85 * @param[in] upstream - indicates direction of the transfer; true indicates
86 * transfer to the host
87 *
88 * @return returns 0 on success, negative errno on failure
89 */
90 int transferDataHost(const fs::path& path, uint32_t offset, uint32_t length,
91 uint64_t address, bool upstream);
92};
Tom Josephf8329ac2019-04-11 22:13:22 +053093
Eddie James3b02e272019-04-22 20:13:55 +000094/** @brief Transfer the data between BMC and host using DMA.
95 *
96 * There is a max size for each DMA operation, transferAll API abstracts this
97 * and the requested length is broken down into multiple DMA operations if the
98 * length exceed max size.
99 *
Tom Joseph55306762019-05-02 09:11:26 +0530100 * @tparam[in] T - DMA interface type
101 * @param[in] intf - interface passed to invoke DMA transfer
Eddie James3b02e272019-04-22 20:13:55 +0000102 * @param[in] command - PLDM command
103 * @param[in] path - pathname of the file to transfer data from or to
104 * @param[in] offset - offset in the file
105 * @param[in] length - length of the data to transfer
106 * @param[in] address - DMA address on the host
107 * @param[in] upstream - indicates direction of the transfer; true indicates
108 * transfer to the host
Tom Joseph4e48b442019-06-04 09:23:44 +0530109 * @return PLDM response message
Eddie James3b02e272019-04-22 20:13:55 +0000110 */
Tom Joseph55306762019-05-02 09:11:26 +0530111
112template <class DMAInterface>
Tom Joseph4e48b442019-06-04 09:23:44 +0530113Response transferAll(DMAInterface* intf, uint8_t command, fs::path& path,
114 uint32_t offset, uint32_t length, uint64_t address,
115 bool upstream)
Tom Joseph55306762019-05-02 09:11:26 +0530116{
117 uint32_t origLength = length;
Tom Joseph4e48b442019-06-04 09:23:44 +0530118 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0);
119 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
Tom Joseph55306762019-05-02 09:11:26 +0530120
121 while (length > dma::maxSize)
122 {
123 auto rc = intf->transferDataHost(path, offset, dma::maxSize, address,
124 upstream);
125 if (rc < 0)
126 {
Tom Joseph4e48b442019-06-04 09:23:44 +0530127 encode_rw_file_memory_resp(0, command, PLDM_ERROR, 0, responsePtr);
128 return response;
Tom Joseph55306762019-05-02 09:11:26 +0530129 }
130
131 offset += dma::maxSize;
132 length -= dma::maxSize;
133 address += dma::maxSize;
134 }
135
136 auto rc = intf->transferDataHost(path, offset, length, address, upstream);
137 if (rc < 0)
138 {
Tom Joseph4e48b442019-06-04 09:23:44 +0530139 encode_rw_file_memory_resp(0, command, PLDM_ERROR, 0, responsePtr);
140 return response;
Tom Joseph55306762019-05-02 09:11:26 +0530141 }
142
Tom Joseph4e48b442019-06-04 09:23:44 +0530143 encode_rw_file_memory_resp(0, command, PLDM_SUCCESS, origLength,
144 responsePtr);
145 return response;
Tom Joseph55306762019-05-02 09:11:26 +0530146}
147
148} // namespace dma
Eddie James3b02e272019-04-22 20:13:55 +0000149
Tom Josephf8329ac2019-04-11 22:13:22 +0530150/** @brief Handler for readFileIntoMemory command
151 *
152 * @param[in] request - pointer to PLDM request payload
153 * @param[in] payloadLength - length of the message payload
Tom Joseph4e48b442019-06-04 09:23:44 +0530154 *
155 * @return PLDM response message
Tom Josephf8329ac2019-04-11 22:13:22 +0530156 */
Tom Joseph4e48b442019-06-04 09:23:44 +0530157Response readFileIntoMemory(const uint8_t* request, size_t payloadLength);
Tom Josephf8329ac2019-04-11 22:13:22 +0530158
Eddie James3b02e272019-04-22 20:13:55 +0000159/** @brief Handler for writeFileIntoMemory command
160 *
161 * @param[in] request - pointer to PLDM request payload
162 * @param[in] payloadLength - length of the message payload
Tom Joseph4e48b442019-06-04 09:23:44 +0530163 *
164 * @return PLDM response message
Eddie James3b02e272019-04-22 20:13:55 +0000165 */
Tom Joseph4e48b442019-06-04 09:23:44 +0530166Response writeFileFromMemory(const uint8_t* request, size_t payloadLength);
Tom Joseph19856622019-06-07 10:18:21 +0530167
168/** @brief Handler for GetFileTable command
169 *
170 * @param[in] request - pointer to PLDM request payload
171 * @param[in] payloadLength - length of the message payload
172 *
173 * @return PLDM response message
174 */
175Response getFileTable(const uint8_t* request, size_t payloadLength);
Tom Josephf8329ac2019-04-11 22:13:22 +0530176} // namespace responder
177} // namespace pldm